├── .github
└── workflows
│ └── master_webserveryou.yml
├── Cube
├── assets
│ ├── background.jpg
│ ├── mcu-particle.mp4
│ └── mcu-wave.mp4
├── index.html
├── libs
│ ├── p5.dom.min.js
│ ├── p5.js
│ └── p5.min.js
└── main.js
├── CubeEx
├── index.html
├── libs
│ ├── p5.dom.min.js
│ ├── p5.min.js
│ ├── particle.wasm
│ └── wave.wasm
└── main.js
├── Graphic
├── assets
│ ├── displayNone.png
│ ├── layer1.png
│ ├── layer2.png
│ ├── surface0.png
│ ├── surface1.png
│ └── surface2.png
├── index.html
├── libs
│ ├── p5.dom.min.js
│ ├── p5.js
│ └── p5.min.js
└── main.js
├── HelloParticle
├── README.md
├── build.ts
├── out
│ └── main.wasm
├── package.json
└── src
│ ├── main.cpp
│ ├── main.html
│ └── main.js
├── HelloWave
├── README.md
├── build.ts
├── out
│ └── main.wasm
├── package.json
└── src
│ ├── main.cpp
│ ├── main.html
│ └── main.js
├── LICENSE
├── README.md
├── README_zh.md
└── doc
├── GuiLite3D.gif
├── GuiLiteCube.gif
└── GuiLiteGraphic.gif
/.github/workflows/master_webserveryou.yml:
--------------------------------------------------------------------------------
1 | # Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy
2 | # More GitHub Actions for Azure: https://github.com/Azure/actions
3 |
4 | name: Build and deploy Node.js app to Azure Web App - webserveryou
5 |
6 | on:
7 | push:
8 | branches:
9 | - master
10 |
11 | jobs:
12 | build-and-deploy:
13 | runs-on: ubuntu-latest
14 |
15 | steps:
16 | - uses: actions/checkout@master
17 |
18 | - name: Set up Node.js version
19 | uses: actions/setup-node@v1
20 | with:
21 | node-version: '10.x'
22 |
23 | - name: npm install, build, and test
24 | run: |
25 | npm install
26 | npm run build --if-present
27 | npm run test --if-present
28 |
29 | - name: 'Deploy to Azure Web App'
30 | uses: azure/webapps-deploy@v1
31 | with:
32 | app-name: 'webserveryou'
33 | slot-name: 'production'
34 | publish-profile: ${{ secrets.AzureAppService_PublishProfile_fbe37b879aec4a9d9bc39eb6c17affc5 }}
35 | package: .
--------------------------------------------------------------------------------
/Cube/assets/background.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/idea4good/GuiLiteWeb/3d87779deeedd4af200a37968e7d9874d64598c8/Cube/assets/background.jpg
--------------------------------------------------------------------------------
/Cube/assets/mcu-particle.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/idea4good/GuiLiteWeb/3d87779deeedd4af200a37968e7d9874d64598c8/Cube/assets/mcu-particle.mp4
--------------------------------------------------------------------------------
/Cube/assets/mcu-wave.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/idea4good/GuiLiteWeb/3d87779deeedd4af200a37968e7d9874d64598c8/Cube/assets/mcu-wave.mp4
--------------------------------------------------------------------------------
/Cube/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | GuiLite
6 |
7 |
8 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Cube/libs/p5.dom.min.js:
--------------------------------------------------------------------------------
1 | /*! p5.js v0.9.0 July 01, 2019 */
2 |
3 | !function(t,e){"function"==typeof define&&define.amd?define("p5.dom",["p5"],function(t){e(t)}):"object"==typeof exports?e(require("../p5")):e(t.p5)}(this,function(d){function l(t){var e=document;return"string"==typeof t&&"#"===t[0]?(t=t.slice(1),e=document.getElementById(t)||document):t instanceof d.Element?e=t.elt:t instanceof HTMLElement&&(e=t),e}function c(t,e,i){(e._userNode?e._userNode:document.body).appendChild(t);var n=i?new d.MediaElement(t,e):new d.Element(t,e);return e._elements.push(n),n}d.prototype.select=function(t,e){d._validateParameters("select",arguments);var i=null,n=l(e);return(i="."===t[0]?(t=t.slice(1),(i=n.getElementsByClassName(t)).length?i[0]:null):"#"===t[0]?(t=t.slice(1),n.getElementById(t)):(i=n.getElementsByTagName(t)).length?i[0]:null)?this._wrapElement(i):null},d.prototype.selectAll=function(t,e){d._validateParameters("selectAll",arguments);var i,n=[],r=l(e);if(i="."===t[0]?(t=t.slice(1),r.getElementsByClassName(t)):r.getElementsByTagName(t))for(var o=0;o
2 |
3 |
4 |
5 | GuiLite
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/CubeEx/libs/p5.dom.min.js:
--------------------------------------------------------------------------------
1 | /*! p5.js v0.9.0 July 01, 2019 */
2 |
3 | !function(t,e){"function"==typeof define&&define.amd?define("p5.dom",["p5"],function(t){e(t)}):"object"==typeof exports?e(require("../p5")):e(t.p5)}(this,function(d){function l(t){var e=document;return"string"==typeof t&&"#"===t[0]?(t=t.slice(1),e=document.getElementById(t)||document):t instanceof d.Element?e=t.elt:t instanceof HTMLElement&&(e=t),e}function c(t,e,i){(e._userNode?e._userNode:document.body).appendChild(t);var n=i?new d.MediaElement(t,e):new d.Element(t,e);return e._elements.push(n),n}d.prototype.select=function(t,e){d._validateParameters("select",arguments);var i=null,n=l(e);return(i="."===t[0]?(t=t.slice(1),(i=n.getElementsByClassName(t)).length?i[0]:null):"#"===t[0]?(t=t.slice(1),n.getElementById(t)):(i=n.getElementsByTagName(t)).length?i[0]:null)?this._wrapElement(i):null},d.prototype.selectAll=function(t,e){d._validateParameters("selectAll",arguments);var i,n=[],r=l(e);if(i="."===t[0]?(t=t.slice(1),r.getElementsByClassName(t)):r.getElementsByTagName(t))for(var o=0;o memory.buffer.byteLength) {
30 | const need = Math.ceil((cur + requested - memory.buffer.byteLength) / 65536);
31 | memory.grow(need);
32 | }
33 | memoryState.currentPosition += requested;
34 | return cur;
35 | }
36 | }
37 |
38 | let s = "";
39 | fetch(wasmFilePath).then(response =>
40 | response.arrayBuffer()
41 | ).then(bytes =>
42 | WebAssembly.instantiate(bytes, {
43 | env: {
44 | __syscall0: function __syscall0(n) { return syscall(instance[index], n, []); },
45 | __syscall1: function __syscall1(n, a) { return syscall(instance[index], n, [a]); },
46 | __syscall2: function __syscall2(n, a, b) { return syscall(instance[index], n, [a, b]); },
47 | __syscall3: function __syscall3(n, a, b, c) { return syscall(instance[index], n, [a, b, c]); },
48 | __syscall4: function __syscall4(n, a, b, c, d) { return syscall(instance[index], n, [a, b, c, d]); },
49 | __syscall5: function __syscall5(n, a, b, c, d, e) { return syscall(instance[index], n, [a, b, c, d, e]); },
50 | __syscall6: function __syscall6(n, a, b, c, d, e, f) { return syscall(instance[index], n, [a, b, c, d, e, f]); },
51 | putc_js: function (c) {
52 | c = String.fromCharCode(c);
53 | if (c == "\n") {
54 | console.log(s);
55 | s = "";
56 | } else {
57 | s += c;
58 | }
59 | },
60 |
61 | drawGuiLitePixel: function (x, y, color) {
62 | drawPixel(x, y, color)
63 | }
64 | }
65 | })
66 | ).then(results => {
67 | instance[index] = results.instance
68 | instance[index].exports.main(mode)
69 | }).catch(console.error);
70 | }
71 |
72 | //////////////////////// Cube Code ////////////////////////
73 | const cubeSize = 180;
74 | const gain = 1;
75 | const animationFrames = 200;
76 | let graphic1, graphic2, graphic3;
77 |
78 | function setup() {
79 | createCanvas(500, 500, WEBGL);
80 | angleMode(DEGREES);
81 | graphic1 = createGraphics(240, 320);
82 | graphic2 = createGraphics(240, 320);
83 | graphic3 = createGraphics(240, 320);
84 | graphic3.background(210, 0, 0)
85 | graphic3.fill(255)
86 | graphic3.textSize(64)
87 | graphic3.text(' 👑\nGuiLite\n on 3D', 20, 100);
88 | startWebAssembly(0, 'libs/particle.wasm', drawPixelOnGraphic1);
89 | startWebAssembly(1, 'libs/wave.wasm', drawPixelOnGraphic2);
90 | }
91 |
92 | const faces = [
93 | [0, 0, 0, '255, 0, 0'],
94 | [0, 90, 0, '0, 255, 0'],
95 | [0, 180, 0, '255, 0, 0'],
96 | [0, -90, 0, '0, 255, 0'],
97 | [90, 0, 0, '0, 0, 255'],
98 | [270, 0, 0, '0, 0, 255'],
99 | ];
100 |
101 | function draw() {
102 | const progress = min(frameCount / animationFrames, 1);
103 | background('gray');
104 | noStroke();
105 | rotateX(-30);
106 | rotateY(frameCount);
107 |
108 | if(progress == 1) {
109 | updateGraphic(0);
110 | updateGraphic(1);
111 | }
112 |
113 | faces.forEach((face, i) => {
114 | textureFace(face, i, progress)
115 |
116 | push();
117 | rotateX(face[0] * progress);
118 | rotateY(face[1] * progress);
119 | rotateZ(face[2] * progress);
120 | translate(0, 0, cubeSize / 2 * gain * progress);
121 | plane(cubeSize);
122 | pop();
123 | });
124 | }
125 |
126 | function updateGraphic(index) {
127 | if(!instance[index]){
128 | return;
129 | }
130 |
131 | if (index == 0){
132 | var pointer = instance[index].exports.updateHelloParticle()
133 | var graphic = graphic1
134 | } else{
135 | var pointer = instance[index].exports.updateHelloWave()
136 | var graphic = graphic2
137 | }
138 |
139 | if(mode != 0){
140 | return;
141 | }
142 |
143 | if(buffer == null){
144 | buffer = new Uint8Array(instance[index].exports.memory.buffer)
145 | }
146 | for(let y = 0; y < 320; y++) {
147 | for(let x = 0; x < 240; x++) {
148 | graphic.stroke('rgb(' + buffer[pointer + 1] + ', ' + buffer[pointer + 2] + ', ' + buffer[pointer + 3] + ')')
149 | graphic.rect(x, y, 1, 1);
150 | pointer = pointer + 4;
151 | }
152 | }
153 | }
154 |
155 | function textureFace(face, i, progress) {
156 | if(progress < 1) {
157 | return fill(`rgba(${face[3]}, 0.5)`);
158 | }
159 |
160 | if(i == 0 || i == 2) {
161 |
162 | } else {
163 |
164 | }
165 | switch(i){
166 | case 0:
167 | case 2:
168 | texture(graphic2)
169 | break;
170 | case 1:
171 | case 3:
172 | texture(graphic1)
173 | break;
174 | default:
175 | texture(graphic3)
176 | break;
177 | }
178 | }
179 |
180 | function drawPixelOnGraphic1(x, y, color) {
181 | graphic1.stroke('rgb(' + ((color & 0xff0000) >> 16) + ', ' + ((color & 0xff00) >> 8) + ', ' + (color & 0xff) + ')')
182 | graphic1.rect(x, y, 1, 1);
183 | }
184 |
185 | function drawPixelOnGraphic2(x, y, color) {
186 | graphic2.stroke('rgb(' + ((color & 0xff0000) >> 16) + ', ' + ((color & 0xff00) >> 8) + ', ' + (color & 0xff) + ')')
187 | graphic2.rect(x, y, 1, 1);
188 | }
--------------------------------------------------------------------------------
/Graphic/assets/displayNone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/idea4good/GuiLiteWeb/3d87779deeedd4af200a37968e7d9874d64598c8/Graphic/assets/displayNone.png
--------------------------------------------------------------------------------
/Graphic/assets/layer1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/idea4good/GuiLiteWeb/3d87779deeedd4af200a37968e7d9874d64598c8/Graphic/assets/layer1.png
--------------------------------------------------------------------------------
/Graphic/assets/layer2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/idea4good/GuiLiteWeb/3d87779deeedd4af200a37968e7d9874d64598c8/Graphic/assets/layer2.png
--------------------------------------------------------------------------------
/Graphic/assets/surface0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/idea4good/GuiLiteWeb/3d87779deeedd4af200a37968e7d9874d64598c8/Graphic/assets/surface0.png
--------------------------------------------------------------------------------
/Graphic/assets/surface1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/idea4good/GuiLiteWeb/3d87779deeedd4af200a37968e7d9874d64598c8/Graphic/assets/surface1.png
--------------------------------------------------------------------------------
/Graphic/assets/surface2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/idea4good/GuiLiteWeb/3d87779deeedd4af200a37968e7d9874d64598c8/Graphic/assets/surface2.png
--------------------------------------------------------------------------------
/Graphic/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | GuiLite
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Graphic/libs/p5.dom.min.js:
--------------------------------------------------------------------------------
1 | /*! p5.js v0.9.0 July 01, 2019 */
2 |
3 | !function(t,e){"function"==typeof define&&define.amd?define("p5.dom",["p5"],function(t){e(t)}):"object"==typeof exports?e(require("../p5")):e(t.p5)}(this,function(d){function l(t){var e=document;return"string"==typeof t&&"#"===t[0]?(t=t.slice(1),e=document.getElementById(t)||document):t instanceof d.Element?e=t.elt:t instanceof HTMLElement&&(e=t),e}function c(t,e,i){(e._userNode?e._userNode:document.body).appendChild(t);var n=i?new d.MediaElement(t,e):new d.Element(t,e);return e._elements.push(n),n}d.prototype.select=function(t,e){d._validateParameters("select",arguments);var i=null,n=l(e);return(i="."===t[0]?(t=t.slice(1),(i=n.getElementsByClassName(t)).length?i[0]:null):"#"===t[0]?(t=t.slice(1),n.getElementById(t)):(i=n.getElementsByTagName(t)).length?i[0]:null)?this._wrapElement(i):null},d.prototype.selectAll=function(t,e){d._validateParameters("selectAll",arguments);var i,n=[],r=l(e);if(i="."===t[0]?(t=t.slice(1),r.getElementsByClassName(t)):r.getElementsByTagName(t))for(var o=0;o -240){
66 | displayY -= 10;
67 | }
68 | drawPlane(displayNone, 0, displayY, -100, displayRx);
69 | }
70 |
71 | let layerRx = -1.2
72 | function rotateLayers(){
73 | if (layerRx < 0) {
74 | layerRx += 0.1;
75 | }
76 | showLayers(layer1, layer2, layerRx);
77 | }
78 |
79 | let stepLayerVisibleRect = 0;
80 | function updateLayersVrect(layerRx = -1.2){
81 | if (stepLayerVisibleRect < 100) {
82 | stepLayerVisibleRect++;
83 | }
84 | something.background(255, 0, 0);
85 | something.fill(255, 255, 0);
86 | something.rect(0, 0, stepLayerVisibleRect, stepLayerVisibleRect);
87 | showDisplay(something);
88 |
89 | something.background(255, 255, 0);
90 | something.strokeWeight(4);
91 | something.rect(0, 0, stepLayerVisibleRect, stepLayerVisibleRect);
92 | something.fill(62, 72, 204);
93 | something.textSize(14);
94 | something.textStyle(BOLD);
95 | something.text(' Visble RECT\nLayer 2', stepLayerVisibleRect, stepLayerVisibleRect);
96 | showLayers(layer1, something, layerRx);
97 | }
98 |
99 | function draw() {
100 | background(0);
101 |
102 | switch(step){
103 | case 0:// clear screen
104 | break;
105 | case 1:// show display from side
106 | showDisplay(displayNone);
107 | break;
108 | case 2:// show display from front
109 | rotateDisplay();
110 | break;
111 | case 3:// show display & surfaces
112 | showDisplay(surface1);
113 | showSurface();
114 | break;
115 | case 4:// flip surface
116 | showDisplay(surface0);
117 | shiftSurface();
118 | break;
119 | case 5:// show display & layers
120 | something.background(255, 0, 0);
121 | something.fill(255, 255, 0);
122 | showDisplay(something);
123 | showLayers();
124 | break;
125 | case 6:// demo visble rect
126 | updateLayersVrect();
127 | break;
128 | case 7:// reset display & layers
129 | something.background(255, 0, 0);
130 | something.fill(255, 255, 0);
131 | showDisplay(something);
132 | showLayers();
133 | break;
134 | case 8:// show layers from front
135 | something.background(255, 0, 0);
136 | something.fill(255, 255, 0);
137 | showDisplay(something);
138 | rotateLayers();
139 | stepLayerVisibleRect = 0;
140 | break;
141 | case 9:// demo visible rect again
142 | updateLayersVrect(0);
143 | break;
144 | default:
145 | step = step_surface = step_layer = stepShift = stepLayerVisibleRect = 0;
146 | displayRx = -1.2; displayY = 0;
147 | layerRx = -1.2;
148 | break;
149 | }
150 | angle += 0.05;
151 | }
152 |
--------------------------------------------------------------------------------
/HelloParticle/README.md:
--------------------------------------------------------------------------------
1 | # Hello World in C
2 |
3 | Level: *Advanced*
4 |
5 | This project prints `"Hello World"` using the well known C `printf` function. This function in turn uses several POSIX APIs that are implemented in JavaScript using DOM APIs.
6 |
7 | ### Project Overview
8 |
9 | * `main.c` - Imports `stdio.h` and calls `printf("Hello World")`.
10 | * `main.js` - Initializes a runtime environment for the WebAssembly module and implements the necessary WebAssembly imports.
11 |
12 | ### Things to Explore
13 |
14 | 1. Click Build to compile `main.c` file to `out/main.wasm`.
15 |
16 | 2. Open the `out/main.wasm` file and notice that there's quite a bit of code. This is somewhat surprising given that our program is so small. The vast majority of this code implements the `printf` function.
17 |
18 | 3. Notice the imports section, these are SysCalls. To get this WebAssembly module running you'll have to implement these functions first. However, note that these import names don't actually tell you what SysCalls are used, they are merely function stubs (one for each number of parameters).
19 |
20 | ```
21 | (import "env" "__syscall0" (func $env.__syscall0 (type $t2)))
22 | (import "env" "__syscall3" (func $env.__syscall3 (type $t5)))
23 | (import "env" "__syscall1" (func $env.__syscall1 (type $t8)))
24 | ...
25 | ```
26 |
27 | 4. To figure that out which SysCalls are being used, you'll have to run the module. I ran it and got `45`, `146` and `192`. You can figure out what these numbers mean by looking them up in the [Linux SysCall Reference](https://syscalls.kernelgrok.com/). They are [brk()](http://man7.org/linux/man-pages/man2/brk.2.html), [writev()](http://man7.org/linux/man-pages/man2/writev.2.html) and [mmap()](http://man7.org/linux/man-pages/man2/mmap2.2.html). To make this WebAssembly module run, you'll just have to implement a tiny Linux kernel in JavaScript, no biggie.
28 |
29 | 5. Take a look at `src/main.js`, this file emulates these basic SysCalls in JavaScript.
30 |
31 | 6. `brk()` can be stubbed to return `0`, which is the success error code. `brk()` is used to allocate more memory to a process. WebAssembly does handles memory differently, so there's no need to do special here.
32 |
33 | 7. `mmap2()` is used to request more memory within the process. In our example, it's implemented as a call to the WebAssembly `memory.grow()` function.
34 |
35 | 8. `writev()` is used to write data to files. Its signature is `writev(int fd, const struct iovec *iov, int iovcnt)`. We can ignore the `fd` file descriptor parameter, and focus on the `iov` structure. The problem here is that on the JavaScript side we have a hard time pulling the `struct iovec` abart. We could figure it out, but a neat hack is to call back into the WebAssembly module and have some C code unpack it for us.
36 |
37 | 9. Click Run
38 |
39 | ```
40 | Hello World
41 | ```
--------------------------------------------------------------------------------
/HelloParticle/build.ts:
--------------------------------------------------------------------------------
1 | import * as gulp from "gulp";
2 | import { Service, project } from "@wasm/studio-utils";
3 |
4 | gulp.task("build", async () => {
5 | const data = await Service.compileFile(project.getFile("src/main.cpp"), "cpp", "wasm", "-g -O3");
6 | const outWasm = project.newFile("out/main.wasm", "wasm", true);
7 | outWasm.setData(data);
8 | });
9 |
10 | gulp.task("default", ["build"], async () => {});
11 |
--------------------------------------------------------------------------------
/HelloParticle/out/main.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/idea4good/GuiLiteWeb/3d87779deeedd4af200a37968e7d9874d64598c8/HelloParticle/out/main.wasm
--------------------------------------------------------------------------------
/HelloParticle/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@wasm/hello_world_c",
3 | "description": "",
4 | "version": "1.0.0",
5 | "scripts": {
6 | "build": "gulp --gulpfile ./build.ts"
7 | },
8 | "devDependencies": {
9 | "@wasm/studio-utils": "*",
10 | "gulp": "~3.9.1",
11 | "ts-node": "~5.0.0",
12 | "typescript": "~2.7.2"
13 | },
14 | "wasmStudio": {
15 | "name": "Hello World in C",
16 | "description": "# Hello World in C\n\nPrint \\`Hello World\\` using a minimal POSIX API.\nLevel: *Advanced*\nTopics: Low-Level, Memory, Linux, System Calls",
17 | "icon": "c-lang-file-icon"
18 | }
19 | }
--------------------------------------------------------------------------------
/HelloParticle/src/main.cpp:
--------------------------------------------------------------------------------
1 | #define REAL_TIME_TASK_CYCLE_MS 50
2 |
3 | #define GL_ARGB(a, r, g, b) ((((unsigned int)(a)) << 24) | (((unsigned int)(r)) << 16) | (((unsigned int)(g)) << 8) | ((unsigned int)(b)))
4 | #define GL_ARGB_A(rgb) ((((unsigned int)(rgb)) >> 24) & 0xFF)
5 |
6 | #define GL_RGB(r, g, b) ((0xFF << 24) | (((unsigned int)(r)) << 16) | (((unsigned int)(g)) << 8) | ((unsigned int)(b)))
7 | #define GL_RGB_R(rgb) ((((unsigned int)(rgb)) >> 16) & 0xFF)
8 | #define GL_RGB_G(rgb) ((((unsigned int)(rgb)) >> 8) & 0xFF)
9 | #define GL_RGB_B(rgb) (((unsigned int)(rgb)) & 0xFF)
10 | #define GL_RGB_32_to_16(rgb) (((((unsigned int)(rgb)) & 0xFF) >> 3) | ((((unsigned int)(rgb)) & 0xFC00) >> 5) | ((((unsigned int)(rgb)) & 0xF80000) >> 8))
11 | #define GL_RGB_16_to_32(rgb) ((0xFF << 24) | ((((unsigned int)(rgb)) & 0x1F) << 3) | ((((unsigned int)(rgb)) & 0x7E0) << 5) | ((((unsigned int)(rgb)) & 0xF800) << 8))
12 |
13 | #define ALIGN_HCENTER 0x00000000L
14 | #define ALIGN_LEFT 0x01000000L
15 | #define ALIGN_RIGHT 0x02000000L
16 | #define ALIGN_HMASK 0x03000000L
17 |
18 | #define ALIGN_VCENTER 0x00000000L
19 | #define ALIGN_TOP 0x00100000L
20 | #define ALIGN_BOTTOM 0x00200000L
21 | #define ALIGN_VMASK 0x00300000L
22 |
23 | typedef struct
24 | {
25 | unsigned short year;
26 | unsigned short month;
27 | unsigned short date;
28 | unsigned short day;
29 | unsigned short hour;
30 | unsigned short minute;
31 | unsigned short second;
32 | }T_TIME;
33 |
34 | void register_debug_function(void(*my_assert)(const char* file, int line), void(*my_log_out)(const char* log));
35 | void _assert(const char* file, int line);
36 | #define ASSERT(condition) \
37 | do{ \
38 | if(!(condition))_assert(__FILE__, __LINE__);\
39 | }while(0)
40 | void log_out(const char* log);
41 |
42 | long get_time_in_second();
43 | T_TIME second_to_day(long second);
44 | T_TIME get_time();
45 |
46 | void start_real_timer(void (*func)(void* arg));
47 | void register_timer(int milli_second, void func(void* ptmr, void* parg));
48 |
49 | unsigned int get_cur_thread_id();
50 | void create_thread(unsigned long* thread_id, void* attr, void *(*start_routine) (void *), void* arg);
51 | void thread_sleep(unsigned int milli_seconds);
52 | int build_bmp(const char *filename, unsigned int width, unsigned int height, unsigned char *data);
53 |
54 | typedef struct struct_bitmap_info
55 | {
56 | unsigned short XSize;
57 | unsigned short YSize;
58 | unsigned short BitsPerPixel;
59 | const unsigned char* pData; /* Pointer to picture data (indices) */
60 | } BITMAP_INFO;
61 |
62 | //FONT
63 | typedef struct struct_lattice
64 | {
65 | unsigned int utf8_code;
66 | unsigned char width;
67 | const unsigned char* p_data;
68 | } LATTICE;
69 |
70 | typedef struct struct_font_info
71 | {
72 | unsigned char height;
73 | unsigned int count;
74 | LATTICE* lattice_array;
75 | } FONT_INFO;
76 |
77 | class c_rect
78 | {
79 | public:
80 | c_rect(){Empty();}
81 | c_rect(int left, int top, int right, int bottom){m_left = left;m_top = top;m_right = right;m_bottom = bottom;};
82 | void SetRect( int left, int top, int right, int bottom);
83 | c_rect(const c_rect&);
84 | c_rect& operator=(const c_rect&);
85 | void Empty();
86 | void Offset(int x, int y);
87 | int IsEmpty() const ;
88 | int PtInRect(int x, int y) const ;
89 | int operator==(const c_rect& ) const;
90 | c_rect operator&(const c_rect& aRect) const;
91 | int Width() const {return m_right - m_left + 1;}
92 | int Height() const {return m_bottom - m_top + 1;}
93 |
94 | int m_left;
95 | int m_top;
96 | int m_right;
97 | int m_bottom;
98 | };
99 |
100 | class c_cmd_target;
101 |
102 | #define MSG_TYPE_INVALID 0xFFFF
103 | #define MSG_TYPE_WND 0x0001
104 | #define MSG_TYPE_USR 0x0002
105 | #define USR_MSG_MAX 32
106 |
107 | typedef void (c_cmd_target::*MsgFuncVV)();
108 |
109 | enum MSG_CALLBACK_TYPE
110 | {
111 | MSG_CALLBACK_NULL = 0,
112 | MSG_CALLBACK_VV,
113 | MSG_CALLBACK_IWL,
114 | MSG_CALLBACK_IWV,
115 | MSG_CALLBACK_VWV,
116 | MSG_CALLBACK_VVL,
117 | MSG_CALLBACK_VWL,
118 | MSG_CALLBACK_IVV
119 | };
120 |
121 | typedef union
122 | {
123 | void (c_cmd_target::*func)();
124 | void (c_cmd_target::*func_vwv)(unsigned int w_param);
125 | int (c_cmd_target::*func_iwl)(unsigned int w_param, long l_param);
126 | int (c_cmd_target::*func_iwv)(unsigned int w_param);
127 | void (c_cmd_target::*func_vvl)(long l_param);
128 | void (c_cmd_target::*func_vwl)(unsigned int w_param, long l_param);
129 | int (c_cmd_target::*func_ivv)();
130 | }MSGFUNCS;
131 |
132 | struct GL_MSG_ENTRY
133 | {
134 | unsigned int msgType;
135 | unsigned int msgId;
136 | c_cmd_target* pObject;
137 | MSG_CALLBACK_TYPE callbackType;
138 | MsgFuncVV func;
139 | };
140 |
141 | #define ON_GL_USER_MSG(msgId, func) \
142 | {MSG_TYPE_USR, msgId, 0, MSG_CALLBACK_VWL, (MsgFuncVV)(static_cast(&func))},
143 |
144 | #define GL_DECLARE_MESSAGE_MAP() \
145 | protected: \
146 | virtual const GL_MSG_ENTRY* GetMSgEntries() const; \
147 | private: \
148 | static const GL_MSG_ENTRY mMsgEntries[];
149 |
150 | #define GL_BEGIN_MESSAGE_MAP(theClass) \
151 | const GL_MSG_ENTRY* theClass::GetMSgEntries() const \
152 | { \
153 | return theClass::mMsgEntries; \
154 | } \
155 | const GL_MSG_ENTRY theClass::mMsgEntries[] = \
156 | {
157 |
158 | #define GL_END_MESSAGE_MAP() \
159 | {MSG_TYPE_INVALID, 0, (c_cmd_target*)0, MSG_CALLBACK_NULL, (MsgFuncVV)0}};
160 |
161 | class c_cmd_target
162 | {
163 | public:
164 | c_cmd_target();
165 | virtual ~c_cmd_target();
166 | static int handle_usr_msg(unsigned int msgId, unsigned int wParam, unsigned int lParam);
167 | protected:
168 | void load_cmd_msg();
169 | const GL_MSG_ENTRY* FindMsgEntry(const GL_MSG_ENTRY *pEntry,
170 | unsigned int msgType, unsigned short msgId, unsigned short ctrlId);
171 | private:
172 | static GL_MSG_ENTRY ms_usr_map_entries[USR_MSG_MAX];
173 | static unsigned short ms_user_map_size;
174 | GL_DECLARE_MESSAGE_MAP()
175 | };
176 |
177 | typedef struct
178 | {
179 | unsigned int dwMsgId;
180 | unsigned int dwParam1;
181 | unsigned int dwParam2;
182 | }MSG_INFO;
183 |
184 | #define FIFO_BUFFER_LEN 1024
185 | class c_fifo
186 | {
187 | public:
188 | c_fifo();
189 | int read(void* buf, int len);
190 | int write(void* buf, int len);
191 |
192 | private:
193 | unsigned char m_buf[FIFO_BUFFER_LEN];
194 | int m_head;
195 | int m_tail;
196 | void* m_read_sem;
197 | void* m_write_mutex;
198 | };
199 |
200 | typedef struct struct_font_info FONT_INFO;
201 | typedef struct struct_color_rect COLOR_RECT;
202 | typedef struct struct_bitmap_info BITMAP_INFO;
203 |
204 | //Rebuild gui library once you change this file
205 | enum FONT_TYPE
206 | {
207 | FONT_NULL,
208 | FONT_DEFAULT,
209 | FONT_CUSTOM1,
210 | FONT_CUSTOM2,
211 | FONT_CUSTOM3,
212 | FONT_CUSTOM4,
213 | FONT_CUSTOM5,
214 | FONT_CUSTOM6,
215 | FONT_MAX
216 | };
217 |
218 | enum BITMAP_TYPE
219 | {
220 | BITMAP_CUSTOM1,
221 | BITMAP_CUSTOM2,
222 | BITMAP_CUSTOM3,
223 | BITMAP_CUSTOM4,
224 | BITMAP_CUSTOM5,
225 | BITMAP_CUSTOM6,
226 |
227 | BITMAP_MAX
228 | };
229 |
230 | enum COLOR_TYPE
231 | {
232 | COLOR_WND_FONT,
233 | COLOR_WND_NORMAL,
234 | COLOR_WND_PUSHED,
235 | COLOR_WND_FOCUS,
236 | COLOR_WND_BORDER,
237 |
238 | COLOR_CUSTOME1,
239 | COLOR_CUSTOME2,
240 | COLOR_CUSTOME3,
241 | COLOR_CUSTOME4,
242 | COLOR_CUSTOME5,
243 | COLOR_CUSTOME6,
244 |
245 | COLOR_MAX
246 | };
247 |
248 | class c_theme
249 | {
250 | public:
251 | static int add_font(FONT_TYPE index, const FONT_INFO* font);
252 | static const FONT_INFO* get_font(FONT_TYPE index);
253 |
254 | static int add_bitmap(BITMAP_TYPE index, const BITMAP_INFO* bmp);
255 | static const BITMAP_INFO* get_bmp(BITMAP_TYPE index);
256 |
257 | static int add_color(COLOR_TYPE index, const unsigned int color);
258 | static const unsigned int get_color(COLOR_TYPE index);
259 | };
260 |
261 | #define DEFAULT_MASK_COLOR 0xFF080408
262 | class c_surface;
263 | class c_bitmap
264 | {
265 | public:
266 | static void draw_bitmap(c_surface* surface, int z_order, const BITMAP_INFO *pBitmap, int x, int y, unsigned int mask_rgb = DEFAULT_MASK_COLOR);
267 | static void draw_bitmap(c_surface* surface, int z_order, const BITMAP_INFO* pBitmap, int x, int y, int src_x, int src_y, int width, int height, unsigned int mask_rgb = DEFAULT_MASK_COLOR);
268 | };
269 |
270 | class c_frame_layer
271 | {
272 | public:
273 | c_frame_layer() { fb = 0;}
274 | unsigned short* fb;
275 | c_rect visible_rect;
276 | };
277 |
278 | typedef enum
279 | {
280 | Z_ORDER_LEVEL_0,//view/wave/page
281 | Z_ORDER_LEVEL_1,//dialog
282 | Z_ORDER_LEVEL_2,//editbox/spinbox/listbox/keyboard
283 | Z_ORDER_LEVEL_MAX
284 | }Z_ORDER_LEVEL;
285 |
286 | struct EXTERNAL_GFX_OP
287 | {
288 | void(*draw_pixel)(int x, int y, int rgb);
289 | void(*fill_rect)(int x0, int y0, int x1, int y1, int rgb);
290 | };
291 |
292 | class c_display;
293 | class c_surface {
294 | friend class c_display; friend class c_bitmap;
295 | public:
296 | int get_width() { return m_width; }
297 | int get_height() { return m_height; }
298 | unsigned int get_pixel(int x, int y, unsigned int z_order);
299 |
300 | void draw_pixel(int x, int y, unsigned int rgb, unsigned int z_order);
301 | void fill_rect(int x0, int y0, int x1, int y1, unsigned int rgb, unsigned int z_order);
302 | void draw_hline(int x0, int x1, int y, unsigned int rgb, unsigned int z_order);
303 | void draw_vline(int x, int y0, int y1, unsigned int rgb, unsigned int z_order);
304 | void draw_line(int x0, int y0, int x1, int y1, unsigned int rgb, unsigned int z_order);
305 | void draw_rect(int x0, int y0, int x1, int y1, unsigned int rgb, unsigned int z_order, unsigned int size = 1);
306 |
307 | inline void draw_rect(c_rect rect, unsigned int rgb, unsigned int size, unsigned int z_order)
308 | {
309 | draw_rect(rect.m_left, rect.m_top, rect.m_right, rect.m_bottom, rgb, z_order, size);
310 | }
311 | inline void fill_rect(c_rect rect, unsigned int rgb, unsigned int z_order)
312 | {
313 | fill_rect(rect.m_left, rect.m_top, rect.m_right, rect.m_bottom, rgb, z_order);
314 | }
315 |
316 | int flush_scrren(int left, int top, int right, int bottom);
317 | bool is_valid(c_rect rect);
318 | bool is_active() { return m_is_active; }
319 | c_display* get_display() { return m_display; }
320 |
321 | int set_frame_layer_visible_rect(c_rect& rect, unsigned int z_order);
322 | void set_active(bool flag){m_is_active = flag;}
323 | protected:
324 | virtual void fill_rect_on_fb(int x0, int y0, int x1, int y1, unsigned int rgb);
325 | virtual void draw_pixel_on_fb(int x, int y, unsigned int rgb);
326 | void set_surface(void* wnd_root, Z_ORDER_LEVEL max_z_order);
327 | c_surface(c_display* display, unsigned int width, unsigned int height, unsigned int color_bytes);
328 | int m_width; //in pixels
329 | int m_height; //in pixels
330 | int m_color_bytes; //16 bits, 32 bits only
331 | void* m_fb; //Top frame buffer you could see
332 | c_frame_layer m_frame_layers[Z_ORDER_LEVEL_MAX];//Top layber fb always be 0
333 | void* m_usr;
334 | bool m_is_active;
335 | Z_ORDER_LEVEL m_max_zorder;
336 | Z_ORDER_LEVEL m_top_zorder;
337 | void* m_phy_fb;
338 | int* m_phy_write_index;
339 | c_display* m_display;
340 | };
341 |
342 | class c_surface_no_fb : public c_surface {//No physical framebuffer, memory fb is 32 bits
343 | friend class c_display;
344 | c_surface_no_fb(c_display* display, unsigned int width, unsigned int height, unsigned int color_bytes, struct EXTERNAL_GFX_OP* gfx_op) :
345 | c_surface(display, width, height, color_bytes) {m_gfx_op = gfx_op;}
346 | protected:
347 | virtual void fill_rect_on_fb(int x0, int y0, int x1, int y1, unsigned int rgb);
348 | virtual void draw_pixel_on_fb(int x, int y, unsigned int rgb);
349 | struct EXTERNAL_GFX_OP* m_gfx_op;//Rendering by external method
350 | };
351 |
352 | #define SURFACE_CNT_MAX 6//root + pages
353 |
354 | class c_hid_pipe;
355 | class c_surface;
356 |
357 | class c_display {
358 | friend class c_surface;
359 | public:
360 | c_display(void* phy_fb, unsigned int display_width, unsigned int display_height,
361 | unsigned int surface_width, unsigned int surface_height,
362 | unsigned int color_bytes, unsigned int surface_cnt, EXTERNAL_GFX_OP* gfx_op = 0);
363 | c_surface* alloc_surface(void* usr, Z_ORDER_LEVEL max_zorder);
364 | int merge_surface(c_surface* s1, c_surface* s2, int x0, int x1, int y0, int y2, int offset);
365 | unsigned int get_width() { return m_width; }
366 | unsigned int get_height() { return m_height; }
367 |
368 | void* get_updated_fb(int* width, int* height, bool force_update = false);
369 | int snap_shot(const char* file_name);
370 | private:
371 | unsigned int m_width; //in pixels
372 | unsigned int m_height; //in pixels
373 | unsigned int m_color_bytes; //16 bits, 32 bits only
374 | void* m_phy_fb;
375 | int m_phy_read_index;
376 | int m_phy_write_index;
377 | c_surface* m_surface_group[SURFACE_CNT_MAX];
378 | unsigned int m_surface_cnt;
379 | };
380 |
381 | typedef struct struct_font_info FONT_INFO;
382 | typedef struct struct_color_rect COLOR_RECT;
383 |
384 | class c_wnd;
385 | class c_surface;
386 |
387 | typedef enum
388 | {
389 | ATTR_VISIBLE = 0x80000000L,
390 | ATTR_DISABLED = 0x40000000L,
391 | ATTR_FOCUS = 0x20000000L,
392 | ATTR_MODAL = 0x10000000L// Handle touch action at high priority
393 | }WND_ATTRIBUTION;
394 |
395 | typedef enum
396 | {
397 | STATUS_NORMAL,
398 | STATUS_PUSHED,
399 | STATUS_FOCUSED,
400 | STATUS_DISABLED
401 | }WND_STATUS;
402 |
403 | typedef enum
404 | {
405 | KEY_FORWARD,
406 | KEY_BACKWARD,
407 | KEY_ENTER
408 | }KEY_TYPE;
409 |
410 | typedef enum
411 | {
412 | TOUCH_DOWN,
413 | TOUCH_UP
414 | }TOUCH_ACTION;
415 |
416 | typedef struct struct_wnd_tree
417 | {
418 | c_wnd* p_wnd;
419 | unsigned int resource_id;
420 | const char* str;
421 | short x;
422 | short y;
423 | short width;
424 | short height;
425 | struct struct_wnd_tree* p_child_tree;
426 | }WND_TREE;
427 |
428 | class c_wnd : public c_cmd_target
429 | {
430 | friend class c_dialog;
431 | public:
432 | c_wnd();
433 | virtual ~c_wnd() {};
434 | virtual int connect(c_wnd *parent, unsigned short resource_id, const char* str,
435 | short x, short y, short width, short height, WND_TREE* p_child_tree = 0);
436 | virtual c_wnd* connect_clone(c_wnd *parent, unsigned short resource_id, const char* str,
437 | short x, short y, short width, short height, WND_TREE* p_child_tree = 0);
438 | void disconnect();
439 | virtual c_wnd* clone() = 0;
440 | virtual void on_init_children() {}
441 | virtual void on_paint() {}
442 | virtual void show_window();
443 |
444 | unsigned short get_id() const { return m_resource_id; }
445 | int get_z_order() { return m_z_order; }
446 | c_wnd* get_wnd_ptr(unsigned short id) const;
447 | unsigned int get_attr() const { return m_attr; }
448 | void set_attr(WND_ATTRIBUTION attr);
449 |
450 | void set_str(const char* str) { m_str = str; }
451 | int is_focus_wnd() const;
452 |
453 | void set_font_color(unsigned int color) { m_font_color = color; }
454 | unsigned int get_font_color() { return m_font_color; }
455 | void set_bg_color(unsigned int color) { m_bg_color = color; }
456 | unsigned int get_bg_color() { return m_bg_color; }
457 | void set_font_type(const FONT_INFO *font_type) { m_font_type = font_type; }
458 | const FONT_INFO* get_font_type() { return m_font_type; }
459 |
460 | void set_wnd_pos(short x, short y, short width, short height);
461 | void get_wnd_rect(c_rect &rect) const;
462 | void get_screen_rect(c_rect &rect) const;
463 |
464 | c_wnd* set_child_focus(c_wnd *focus_child);
465 |
466 | c_wnd* get_parent() const { return m_parent; }
467 | c_wnd* get_last_child() const;
468 | int unlink_child(c_wnd *child);
469 | c_wnd* get_prev_sibling() const { return m_prev_sibling; }
470 | c_wnd* get_next_sibling() const { return m_next_sibling; }
471 |
472 | void notify_parent(unsigned int msg_id, unsigned int ctrl_id, int param);
473 |
474 | virtual bool on_touch(int x, int y, TOUCH_ACTION action);// return true: handled; false: not be handled.
475 | virtual bool on_key(KEY_TYPE key);// return false: skip handling by parent;
476 |
477 | c_surface* get_surface() { return m_surface; }
478 | void set_surface(c_surface* surface) { m_surface = surface; }
479 | protected:
480 | virtual void pre_create_wnd() {};
481 | void add_child_2_tail(c_wnd *child);
482 |
483 | void wnd2screen(int &x, int &y) const;
484 | void wnd2screen(c_rect &rect) const;
485 | void screen2wnd(short &x, short &y) const;
486 | void screen2wnd(c_rect &rect) const;
487 |
488 | int load_child_wnd(WND_TREE *p_child_tree);
489 | int load_clone_child_wnd(WND_TREE *p_child_tree);
490 | void set_active_child(c_wnd* child) { m_focus_child = child; }
491 |
492 | virtual void on_focus() {};
493 | virtual void on_kill_focus() {};
494 | protected:
495 | WND_STATUS m_status;
496 | WND_ATTRIBUTION m_attr;
497 | c_rect m_wnd_rect;// position relative to parent wnd.
498 | c_wnd* m_parent;
499 | c_wnd* m_top_child;
500 | c_wnd* m_prev_sibling;
501 | c_wnd* m_next_sibling;
502 | const char* m_str;
503 |
504 | const FONT_INFO* m_font_type;
505 | unsigned int m_font_color;
506 | unsigned int m_bg_color;
507 |
508 | unsigned short m_resource_id;
509 |
510 | int m_z_order;
511 | c_wnd* m_focus_child;//current focused wnd
512 | c_surface* m_surface;
513 | private:
514 | c_wnd(const c_wnd &win);
515 | c_wnd& operator=(const c_wnd &win);
516 | };
517 |
518 | class c_surface;
519 | class c_word
520 | {
521 | public:
522 | static void draw_string(c_surface* surface, int z_order, const char *s, int x, int y, const FONT_INFO* font, unsigned int font_color, unsigned int bg_color, unsigned int align_type = ALIGN_LEFT);
523 | static void draw_string_in_rect(c_surface* surface, int z_order, const char *s, c_rect rect, const FONT_INFO* font, unsigned int font_color, unsigned int bg_color, unsigned int align_type = ALIGN_LEFT);
524 | static void draw_value(c_surface* surface, int z_order, int value, int dot_position, int x, int y, const FONT_INFO* font, unsigned int font_color, unsigned int bg_color, unsigned int align_type = ALIGN_LEFT);
525 | static void draw_value_in_rect(c_surface* surface, int z_order, int value, int dot_position, c_rect rect, const FONT_INFO* font, unsigned int font_color, unsigned int bg_color, unsigned int align_type = ALIGN_LEFT);
526 | static void value_2_string(int value, int dot_position, char* buf, int len);
527 |
528 | static int get_str_size(const char *s, const FONT_INFO* font, int& width, int& height);
529 | private:
530 | static int draw_single_char(c_surface* surface, int z_order, unsigned int utf8_code, int x, int y, const FONT_INFO* font, unsigned int font_color, unsigned int bg_color);
531 | static void draw_lattice(c_surface* surface, int z_order, int x, int y, int width, int height, const unsigned char* p_data, unsigned int font_color, unsigned int bg_color);
532 |
533 | static const LATTICE* get_lattice(const FONT_INFO* font, unsigned int utf8_code);
534 | static void get_string_pos(const char *s, const FONT_INFO* font, c_rect rect, unsigned int align_type, int &x, int &y);
535 | };
536 |
537 | ///////////////////////////////
538 |
539 |
540 | void c_bitmap::draw_bitmap(c_surface* surface, int z_order, const BITMAP_INFO *pBitmap, int x, int y, unsigned int mask_rgb)
541 | {
542 | if (0 == pBitmap)
543 | {
544 | return;
545 | }
546 | unsigned short* lower_fb = 0;
547 | int lower_fb_width = surface->m_width;
548 | if (z_order >= Z_ORDER_LEVEL_1)
549 | {
550 | lower_fb = surface->m_frame_layers[z_order - 1].fb;
551 | }
552 | unsigned int mask_rgb_16 = GL_RGB_32_to_16(mask_rgb);
553 | int xsize = pBitmap->XSize;
554 | int ysize = pBitmap->YSize;
555 | const unsigned short* pData = (const unsigned short*)pBitmap->pData;
556 | for (int j = 0; j < ysize; j++)
557 | {
558 | for (int i = 0; i < xsize; i++)
559 | {
560 | unsigned int rgb = *pData++;
561 | if (mask_rgb_16 == rgb)
562 | {
563 | if (lower_fb)
564 | {//restore lower layer
565 | surface->draw_pixel(x + i, y + j, GL_RGB_16_to_32(lower_fb[(y + j) * lower_fb_width + x + i]), z_order);
566 | }
567 | }
568 | else
569 | {
570 | surface->draw_pixel(x + i, y + j, GL_RGB_16_to_32(rgb), z_order);
571 | }
572 | }
573 | }
574 | }
575 |
576 | void c_bitmap::draw_bitmap(c_surface* surface, int z_order, const BITMAP_INFO* pBitmap, int x, int y, int src_x, int src_y, int width, int height, unsigned int mask_rgb)
577 | {
578 | if (0 == pBitmap || (src_x + width > pBitmap->XSize) || (src_y + height > pBitmap->YSize))
579 | {
580 | return;
581 | }
582 |
583 | unsigned short* lower_fb = 0;
584 | int lower_fb_width = surface->m_width;
585 | if (z_order >= Z_ORDER_LEVEL_1)
586 | {
587 | lower_fb = surface->m_frame_layers[z_order - 1].fb;
588 | }
589 | unsigned int mask_rgb_16 = GL_RGB_32_to_16(mask_rgb);
590 | const unsigned short* pData = (const unsigned short*)pBitmap->pData;
591 | for (int j = 0; j < height; j++)
592 | {
593 | const unsigned short* p = &pData[src_x + (src_y + j) * pBitmap->XSize];
594 | for (int i = 0; i < width; i++)
595 | {
596 | unsigned int rgb = *p++;
597 | if (mask_rgb_16 == rgb)
598 | {
599 | if (lower_fb)
600 | {//restore lower layer
601 | surface->draw_pixel(x + i, y + j, GL_RGB_16_to_32(lower_fb[(y + j) * lower_fb_width + x + i]), z_order);
602 | }
603 | }
604 | else
605 | {
606 | surface->draw_pixel(x + i, y + j, GL_RGB_16_to_32(rgb), z_order);
607 | }
608 | }
609 | }
610 | }
611 |
612 | GL_MSG_ENTRY c_cmd_target::ms_usr_map_entries[USR_MSG_MAX];
613 | unsigned short c_cmd_target::ms_user_map_size;
614 |
615 | GL_BEGIN_MESSAGE_MAP(c_cmd_target)
616 | GL_END_MESSAGE_MAP()
617 |
618 | c_cmd_target::c_cmd_target()
619 | {
620 | }
621 |
622 | c_cmd_target::~c_cmd_target()
623 | {
624 | }
625 |
626 | int c_cmd_target::handle_usr_msg(unsigned int msgId, unsigned int wParam, unsigned int lParam)
627 | {
628 | int i;
629 | c_cmd_target* p_wnd = 0;
630 | MSGFUNCS msg_funcs;
631 | for (i = 0; i < ms_user_map_size; i++)
632 | {
633 | if (msgId == ms_usr_map_entries[i].msgId)
634 | {
635 | p_wnd = (c_cmd_target*)ms_usr_map_entries[i].pObject;
636 | msg_funcs.func = ms_usr_map_entries[i].func;
637 | (p_wnd->*msg_funcs.func_vwl)(wParam , lParam);
638 | }
639 | }
640 | return 1;
641 | }
642 |
643 | void c_cmd_target::load_cmd_msg()
644 | {
645 | const GL_MSG_ENTRY* p_entry = GetMSgEntries();
646 | if (0 == p_entry)
647 | {
648 | return;
649 | }
650 |
651 | bool bExist = false;
652 | while(MSG_TYPE_INVALID != p_entry->msgType)
653 | {
654 | if (MSG_TYPE_WND == p_entry->msgType)
655 | {
656 | p_entry++;
657 | continue;
658 | }
659 |
660 | bExist = false;
661 | for (int i = 0; i < ms_user_map_size; i++)
662 | {
663 | //repeat register, return.
664 | if (p_entry->msgId == ms_usr_map_entries[i].msgId
665 | && ms_usr_map_entries[i].pObject == this)
666 | {
667 | bExist = true;
668 | break;
669 | }
670 | }
671 | if (true == bExist)
672 | {
673 | p_entry++;
674 | continue;
675 | }
676 |
677 | if (MSG_TYPE_USR == p_entry->msgType)
678 | {
679 | ms_usr_map_entries[ms_user_map_size] = *p_entry;
680 | ms_usr_map_entries[ms_user_map_size].pObject = this;
681 | ms_user_map_size++;
682 | if (USR_MSG_MAX == ms_user_map_size)
683 | {
684 | ASSERT(false);
685 | }
686 | }
687 | else
688 | {
689 | ASSERT(false);
690 | break;
691 | }
692 | p_entry++;
693 | }
694 | }
695 |
696 | const GL_MSG_ENTRY* c_cmd_target::FindMsgEntry(const GL_MSG_ENTRY *pEntry,
697 | unsigned int msgType, unsigned short msgId, unsigned short ctrlId)
698 | {
699 | if ( MSG_TYPE_INVALID == msgType)
700 | {
701 | return 0;
702 | }
703 |
704 | while (MSG_CALLBACK_NULL != pEntry->callbackType)
705 | {
706 | if ( (msgType == pEntry->msgType) && (msgId == pEntry->msgId) && (void*)(unsigned long)ctrlId == pEntry->pObject)
707 | {
708 | return pEntry;
709 | }
710 | pEntry++;
711 | }
712 | return 0;
713 | }
714 |
715 | #include
716 | #include
717 |
718 | c_display::c_display(void* phy_fb, unsigned int display_width, unsigned int display_height,
719 | unsigned int surface_width, unsigned int surface_height,
720 | unsigned int color_bytes, unsigned int surface_cnt, EXTERNAL_GFX_OP* gfx_op)
721 | {
722 | if (color_bytes != 2 && color_bytes != 4)
723 | {
724 | log_out("Support 16 bits, 32 bits color only!");
725 | ASSERT(false);
726 | }
727 |
728 | m_width = display_width;
729 | m_height = display_height;
730 | m_color_bytes = color_bytes;
731 | m_phy_fb = phy_fb;
732 | m_phy_read_index = m_phy_write_index = 0;
733 | memset(m_surface_group, 0, sizeof(m_surface_group));
734 | m_surface_cnt = surface_cnt;
735 | ASSERT(m_surface_cnt <= SURFACE_CNT_MAX);
736 |
737 | for (int i = 0; i < m_surface_cnt; i++)
738 | {
739 | m_surface_group[i] = phy_fb ? new c_surface(this, surface_width, surface_height, color_bytes) : new c_surface_no_fb(this, surface_width, surface_height, color_bytes, gfx_op);
740 | }
741 | }
742 |
743 | c_surface* c_display::alloc_surface(void* usr, Z_ORDER_LEVEL max_zorder)
744 | {
745 | int i = 0;
746 | ASSERT(max_zorder < Z_ORDER_LEVEL_MAX);
747 |
748 | while (i < m_surface_cnt)
749 | {
750 | if (m_surface_group[i]->m_usr == usr)
751 | {
752 | //repeat register
753 | ASSERT(false);
754 | return m_surface_group[i];
755 | }
756 | i++;
757 | }
758 |
759 | i = 0;
760 | while (i < m_surface_cnt)
761 | {
762 | if (m_surface_group[i]->m_usr == 0)
763 | {
764 | m_surface_group[i]->set_surface(usr, max_zorder);
765 | return m_surface_group[i];
766 | }
767 | i++;
768 | }
769 | //no surface for use
770 | ASSERT(false);
771 | return 0;
772 | }
773 |
774 | int c_display::merge_surface(c_surface* s0, c_surface* s1, int x0, int x1, int y0, int y1, int offset)
775 | {
776 | int surface_width = s0->get_width();
777 | int surface_height = s0->get_height();
778 |
779 | if (offset < 0 || offset > surface_width || y0 < 0 || y0 >= surface_height ||
780 | y1 < 0 || y1 >= surface_height || x0 < 0 || x0 >= surface_width || x1 < 0 || x1 >= surface_width)
781 | {
782 | ASSERT(false);
783 | return -1;
784 | }
785 |
786 | int width = (x1 - x0 + 1);
787 | if (width < 0 || width > surface_width || width < offset)
788 | {
789 | ASSERT(false);
790 | return -1;
791 | }
792 |
793 | x0 = (x0 >= m_width) ? (m_width - 1) : x0;
794 | x1 = (x1 >= m_width) ? (m_width - 1) : x1;
795 | y0 = (y0 >= m_height) ? (m_height - 1) : y0;
796 | y1 = (y1 >= m_height) ? (m_height - 1) : y1;
797 |
798 | if (m_phy_fb)
799 | {
800 | for (int y = y0; y <= y1; y++)
801 | {
802 | //Left surface
803 | char* addr_s = ((char*)(s0->m_fb) + (y * (s0->get_width()) + x0 + offset) * m_color_bytes);
804 | char* addr_d = ((char*)(m_phy_fb)+(y * m_width + x0) * m_color_bytes);
805 | memcpy(addr_d, addr_s, (width - offset) * m_color_bytes);
806 | //Right surface
807 | addr_s = ((char*)(s1->m_fb) + (y * (s1->get_width()) + x0) * m_color_bytes);
808 | addr_d = ((char*)(m_phy_fb)+(y * m_width + x0 + (width - offset)) * m_color_bytes);
809 | memcpy(addr_d, addr_s, offset * m_color_bytes);
810 | }
811 | }
812 | else if(m_color_bytes == 4)
813 | {
814 | void(*draw_pixel)(int x, int y, int rgb) = ((c_surface_no_fb*)s0)->m_gfx_op->draw_pixel;
815 | for (int y = y0; y <= y1; y++)
816 | {
817 | //Left surface
818 | for (int x = x0; x <= (x1 - offset); x++)
819 | {
820 | draw_pixel(x, y, ((unsigned int*)s0->m_fb)[y * m_width + x + offset]);
821 | }
822 | //Right surface
823 | for (int x = x1 - offset; x <= x1; x++)
824 | {
825 | draw_pixel(x, y, ((unsigned int*)s1->m_fb)[y * m_width + x + offset - x1 + x0]);
826 | }
827 | }
828 | }
829 | else if (m_color_bytes == 2)
830 | {
831 | void(*draw_pixel)(int x, int y, int rgb) = ((c_surface_no_fb*)s0)->m_gfx_op->draw_pixel;
832 | for (int y = y0; y <= y1; y++)
833 | {
834 | //Left surface
835 | for (int x = x0; x <= (x1 - offset); x++)
836 | {
837 | draw_pixel(x, y, GL_RGB_16_to_32(((unsigned short*)s0->m_fb)[y * m_width + x + offset]));
838 | }
839 | //Right surface
840 | for (int x = x1 - offset; x <= x1; x++)
841 | {
842 | draw_pixel(x, y, GL_RGB_16_to_32(((unsigned short*)s1->m_fb)[y * m_width + x + offset - x1 + x0]));
843 | }
844 | }
845 | }
846 |
847 | m_phy_write_index++;
848 | return 0;
849 | }
850 |
851 | void* c_display::get_updated_fb(int* width, int* height, bool force_update)
852 | {
853 | if (width && height)
854 | {
855 | *width = get_width();
856 | *height = get_height();
857 | }
858 | if (force_update)
859 | {
860 | return m_phy_fb;
861 | }
862 | if (m_phy_read_index == m_phy_write_index)
863 | {//No update
864 | return 0;
865 | }
866 | m_phy_read_index = m_phy_write_index;
867 | return m_phy_fb;
868 | }
869 |
870 | int c_display::snap_shot(const char* file_name)
871 | {
872 | if (!m_phy_fb)
873 | {
874 | return -1;
875 | }
876 |
877 | unsigned int width = get_width();
878 | unsigned int height = get_height();
879 |
880 | //16 bits framebuffer
881 | if (m_color_bytes == 2)
882 | {
883 | return build_bmp(file_name, width, height, (unsigned char*)m_phy_fb);
884 | }
885 |
886 | //32 bits framebuffer
887 | unsigned short* p_bmp565_data = new unsigned short[width * height];
888 | unsigned int* p_raw_data = (unsigned int*)m_phy_fb;
889 |
890 | for (int i = 0; i < width * height; i++)
891 | {
892 | unsigned int rgb = *p_raw_data++;
893 | p_bmp565_data[i] = GL_RGB_32_to_16(rgb);
894 | }
895 |
896 | int ret = build_bmp(file_name, width, height, (unsigned char*)p_bmp565_data);
897 | delete []p_bmp565_data;
898 | return ret;
899 | }
900 |
901 | #define MAX(a,b) (((a)>(b))?(a):(b))
902 | #define MIN(a,b) (((a)<(b))?(a):(b))
903 |
904 | c_rect::c_rect(const c_rect& rect)
905 | {
906 | SetRect(rect.m_left,rect.m_top,rect.m_right,rect.m_bottom);
907 | }
908 |
909 | c_rect& c_rect::operator=(const c_rect& rect)
910 | {
911 | SetRect(rect.m_left,rect.m_top,rect.m_right,rect.m_bottom);
912 | return *this;
913 | }
914 |
915 | void c_rect::SetRect( int Left, int Top, int Right, int Bottom)
916 | {
917 | m_left = MIN(Left, Right);
918 | m_top = MIN(Top, Bottom);
919 | m_right = MAX(Left, Right);
920 | m_bottom = MAX(Top, Bottom);
921 | }
922 |
923 | c_rect c_rect::operator&(const c_rect& rect) const
924 | {
925 | c_rect dst;
926 | dst.m_left = MAX(m_left, rect.m_left);
927 | dst.m_top = MAX(m_top, rect.m_top);
928 | dst.m_right = MIN(m_right, rect.m_right);
929 | dst.m_bottom = MIN(m_bottom, rect.m_bottom);
930 | if(dst.m_left >= dst.m_right || dst.m_top >= dst.m_bottom)
931 | dst.Empty();
932 | return dst;
933 | }
934 |
935 | void c_rect::Empty()
936 | {
937 | m_left = m_top = m_right = m_bottom = 0;
938 | }
939 |
940 | void c_rect::Offset(int x, int y)
941 | {
942 | m_left +=x;
943 | m_right +=x;
944 | m_top += y;
945 | m_bottom += y;
946 | }
947 |
948 | int c_rect::IsEmpty() const
949 | {
950 | return m_top == m_bottom || m_left == m_right;
951 | }
952 |
953 | int c_rect::PtInRect(int x, int y) const
954 | {
955 | return x >= m_left && x <= m_right && y >= m_top && y <= m_bottom;
956 | }
957 |
958 | int c_rect::operator==(const c_rect& rect) const
959 | {
960 | return (m_left == rect.m_left) && (m_top==rect.m_top) &&
961 | (m_right == rect.m_right) && (m_bottom==rect.m_bottom);
962 | }
963 |
964 |
965 | #include
966 | #include
967 |
968 | #define GL_ROUND_RGB_32(rgb) (rgb & 0xFFF8FCF8) //make RGB32 = RGB16
969 |
970 | c_surface::c_surface(c_display* display, unsigned int width, unsigned int height, unsigned int color_bytes)
971 | {
972 | m_width = width;
973 | m_height = height;
974 | m_color_bytes = color_bytes;
975 | m_display = display;
976 | m_phy_fb = display->m_phy_fb;
977 | m_phy_write_index = &display->m_phy_write_index;
978 | m_fb = m_usr = 0;
979 | m_top_zorder = m_max_zorder = Z_ORDER_LEVEL_0;
980 | m_is_active = false;
981 | m_frame_layers[Z_ORDER_LEVEL_0].visible_rect = c_rect(0, 0, m_width, m_height);
982 | }
983 |
984 | void c_surface::set_surface(void* wnd_root, Z_ORDER_LEVEL max_z_order)
985 | {
986 | m_usr = wnd_root;
987 | m_max_zorder = max_z_order;
988 |
989 | if (m_display->m_surface_cnt > 1)
990 | {
991 | m_fb = calloc(m_width * m_height, m_color_bytes);
992 | }
993 |
994 | for(int i = Z_ORDER_LEVEL_0; i < m_max_zorder; i++)
995 | {//Top layber fb always be 0
996 | m_frame_layers[i].fb = (unsigned short*)calloc(m_width * m_height, sizeof(unsigned short));
997 | ASSERT(0 != m_frame_layers[i].fb);
998 | }
999 | }
1000 |
1001 | void c_surface::draw_pixel(int x, int y, unsigned int rgb, unsigned int z_order)
1002 | {
1003 | if (x >= m_width || y >= m_height || x < 0 || y < 0)
1004 | {
1005 | return;
1006 | }
1007 | if (z_order > m_max_zorder)
1008 | {
1009 | ASSERT(false);
1010 | return;
1011 | }
1012 | rgb = GL_ROUND_RGB_32(rgb);
1013 | if (z_order == m_max_zorder)
1014 | {
1015 | return draw_pixel_on_fb(x, y, rgb);
1016 | }
1017 |
1018 | if (z_order > m_top_zorder)
1019 | {
1020 | m_top_zorder = (Z_ORDER_LEVEL)z_order;
1021 | }
1022 |
1023 | if (0 == m_frame_layers[z_order].visible_rect.PtInRect(x, y))
1024 | {
1025 | ASSERT(false);
1026 | return;
1027 | }
1028 | ((unsigned short*)(m_frame_layers[z_order].fb))[x + y * m_width] = GL_RGB_32_to_16(rgb);
1029 |
1030 | if (z_order == m_top_zorder)
1031 | {
1032 | return draw_pixel_on_fb(x, y, rgb);
1033 | }
1034 |
1035 | bool is_covered = false;
1036 | for (int tmp_z_order = Z_ORDER_LEVEL_MAX - 1; tmp_z_order > z_order; tmp_z_order--)
1037 | {
1038 | if (true == m_frame_layers[tmp_z_order].visible_rect.PtInRect(x, y))
1039 | {
1040 | is_covered = true;
1041 | break;
1042 | }
1043 | }
1044 |
1045 | if (!is_covered)
1046 | {
1047 | draw_pixel_on_fb(x, y, rgb);
1048 | }
1049 | }
1050 |
1051 | void c_surface::draw_pixel_on_fb(int x, int y, unsigned int rgb)
1052 | {
1053 | if (m_fb)
1054 | {
1055 | (m_color_bytes == 4) ? ((unsigned int*)m_fb)[y * m_width + x] = rgb : ((unsigned short*)m_fb)[y * m_width + x] = GL_RGB_32_to_16(rgb);
1056 | }
1057 |
1058 | int display_width = m_display->get_width();
1059 | int display_height = m_display->get_height();
1060 | if (m_is_active && (x < display_width) && (y < display_height))
1061 | {
1062 | if (m_color_bytes == 4)
1063 | {
1064 | ((unsigned int*)m_phy_fb)[y * (m_display->get_width()) + x] = rgb;
1065 | }
1066 | else
1067 | {
1068 | ((unsigned short*)m_phy_fb)[y * (m_display->get_width()) + x] = GL_RGB_32_to_16(rgb);
1069 | }
1070 | *m_phy_write_index = *m_phy_write_index + 1;
1071 | }
1072 | }
1073 |
1074 | void c_surface::fill_rect(int x0, int y0, int x1, int y1, unsigned int rgb, unsigned int z_order)
1075 | {
1076 | rgb = GL_ROUND_RGB_32(rgb);
1077 | if (z_order == m_max_zorder)
1078 | {
1079 | return fill_rect_on_fb(x0, y0, x1, y1, rgb);
1080 | }
1081 |
1082 | if (z_order == m_top_zorder)
1083 | {
1084 | int x, y;
1085 | unsigned short *mem_fb;
1086 | unsigned int rgb_16 = GL_RGB_32_to_16(rgb);
1087 | for (y = y0; y <= y1; y++)
1088 | {
1089 | x = x0;
1090 | mem_fb = &((unsigned short*)m_frame_layers[z_order].fb)[y * m_width + x];
1091 | for (; x <= x1; x++)
1092 | {
1093 | *mem_fb++ = rgb_16;
1094 | }
1095 | }
1096 | return fill_rect_on_fb(x0, y0, x1, y1, rgb);
1097 | }
1098 |
1099 | for (; y0 <= y1; y0++)
1100 | {
1101 | draw_hline(x0, x1, y0, rgb, z_order);
1102 | }
1103 | }
1104 |
1105 | void c_surface::fill_rect_on_fb(int x0, int y0, int x1, int y1, unsigned int rgb)
1106 | {
1107 | if (x0 < 0 || y0 < 0 || x1 < 0 || y1 < 0 ||
1108 | x0 >= m_width || x1 >= m_width || y0 >= m_height || y1 >= m_height)
1109 | {
1110 | ASSERT(false);
1111 | }
1112 | int display_width = m_display->get_width();
1113 | int display_height = m_display->get_height();
1114 |
1115 | if (m_color_bytes == 4)
1116 | {
1117 | int x;
1118 | unsigned int *fb, *phy_fb;
1119 | for (; y0 <= y1; y0++)
1120 | {
1121 | x = x0;
1122 | fb = m_fb ? &((unsigned int*)m_fb)[y0 * m_width + x] : 0;
1123 | phy_fb = &((unsigned int*)m_phy_fb)[y0 * display_width + x];
1124 | *m_phy_write_index = *m_phy_write_index + 1;
1125 | for (; x <= x1; x++)
1126 | {
1127 | if (fb)
1128 | {
1129 | *fb++ = rgb;
1130 | }
1131 | if (m_is_active && (x < display_width) && (y0 < display_height))
1132 | {
1133 | *phy_fb++ = rgb;
1134 | }
1135 | }
1136 | }
1137 | }
1138 | else if(m_color_bytes == 2)
1139 | {
1140 | int x;
1141 | unsigned short *fb, *phy_fb;
1142 | rgb = GL_RGB_32_to_16(rgb);
1143 | for (; y0 <= y1; y0++)
1144 | {
1145 | x = x0;
1146 | fb = m_fb ? &((unsigned short*)m_fb)[y0 * m_width + x] : 0;
1147 | phy_fb = &((unsigned short*)m_phy_fb)[y0 * display_width + x];
1148 | *m_phy_write_index = *m_phy_write_index + 1;
1149 | for (; x <= x1; x++)
1150 | {
1151 | if (fb)
1152 | {
1153 | *fb++ = rgb;
1154 | }
1155 | if (m_is_active && (x < display_width) && (y0 < display_height))
1156 | {
1157 | *phy_fb++ = rgb;
1158 | }
1159 | }
1160 | }
1161 | }
1162 |
1163 | }
1164 |
1165 | unsigned int c_surface::get_pixel(int x, int y, unsigned int z_order)
1166 | {
1167 | if (x >= m_width || y >= m_height || x < 0 || y < 0 ||
1168 | z_order >= Z_ORDER_LEVEL_MAX)
1169 | {
1170 | ASSERT(false);
1171 | return 0;
1172 | }
1173 |
1174 | if (z_order == m_max_zorder)
1175 | {
1176 | if (m_fb)
1177 | {
1178 | return (m_color_bytes == 4) ? ((unsigned int*)m_fb)[y * m_width + x] : GL_RGB_16_to_32(((unsigned short*)m_fb)[y * m_width + x]);
1179 | }
1180 | else if(m_phy_fb)
1181 | {
1182 | return (m_color_bytes == 4) ? ((unsigned int*)m_phy_fb)[y * m_width + x] : GL_RGB_16_to_32(((unsigned short*)m_phy_fb)[y * m_width + x]);
1183 | }
1184 | return 0;
1185 | }
1186 |
1187 | unsigned short rgb_16 = ((unsigned short*)(m_frame_layers[z_order].fb))[y * m_width + x];
1188 | return GL_RGB_16_to_32(rgb_16);
1189 | }
1190 |
1191 | void c_surface::draw_hline(int x0, int x1, int y, unsigned int rgb, unsigned int z_order)
1192 | {
1193 | for (;x0 <= x1; x0++)
1194 | { draw_pixel(x0, y, rgb, z_order); }
1195 | }
1196 |
1197 | void c_surface::draw_vline(int x, int y0, int y1, unsigned int rgb, unsigned int z_order)
1198 | {
1199 | for (;y0 <= y1; y0++)
1200 | { draw_pixel(x, y0, rgb, z_order); }
1201 | }
1202 |
1203 | void c_surface::draw_line(int x1, int y1, int x2, int y2, unsigned int rgb, unsigned int z_order)
1204 | {
1205 | int dx, dy, e;
1206 | dx = x2 - x1;
1207 | dy = y2 - y1;
1208 |
1209 | if ((dx >= 0) && (dy >= 0))
1210 | {
1211 | if (dx >= dy)
1212 | {
1213 | e = dy - dx / 2;
1214 | for(; x1 <= x2; x1++, e += dy)
1215 | {
1216 | draw_pixel(x1, y1, rgb, z_order);
1217 | if (e>0) { y1++; e -= dx; }
1218 | }
1219 | }
1220 | else
1221 | {
1222 | e = dx - dy / 2;
1223 | for(; y1 <= y2; y1++, e += dx)
1224 | {
1225 | draw_pixel(x1, y1, rgb, z_order);
1226 | if (e>0) { x1++; e -= dy; }
1227 | }
1228 | }
1229 | }
1230 |
1231 | else if ((dx >= 0) && (dy < 0))
1232 | {
1233 | dy = -dy;
1234 | if (dx >= dy)
1235 | {
1236 | e = dy - dx / 2;
1237 | for(; x1 <= x2; x1++, e += dy)
1238 | {
1239 | draw_pixel(x1, y1, rgb, z_order);
1240 | if (e>0) { y1--; e -= dx; }
1241 | }
1242 | }
1243 | else
1244 | {
1245 | e = dx - dy / 2;
1246 | for(; y1 >= y2; y1--, e += dx)
1247 | {
1248 | draw_pixel(x1, y1, rgb, z_order);
1249 | if (e>0) { x1++; e -= dy; }
1250 | }
1251 | }
1252 | }
1253 |
1254 | else if ((dx < 0) && (dy >= 0))
1255 | {
1256 | dx = -dx;
1257 | if (dx >= dy)
1258 | {
1259 | e = dy - dx / 2;
1260 | for(; x1 >= x2; x1--, e += dy)
1261 | {
1262 | draw_pixel(x1, y1, rgb, z_order);
1263 | if (e>0) { y1++; e -= dx; }
1264 | }
1265 | }
1266 | else
1267 | {
1268 | e = dx - dy / 2;
1269 | for(; y1 <= y2; y1++, e += dx)
1270 | {
1271 | draw_pixel(x1, y1, rgb, z_order);
1272 | if (e>0) { x1--; e -= dy; }
1273 | }
1274 | }
1275 | }
1276 |
1277 | else if ((dx < 0) && (dy < 0))
1278 | {
1279 | dx = -dx;
1280 | dy = -dy;
1281 | if (dx >= dy)
1282 | {
1283 | e = dy - dx / 2;
1284 | for(; x1 >= x2; x1--, e += dy)
1285 | {
1286 | draw_pixel(x1, y1, rgb, z_order);
1287 | if (e>0) { y1--; e -= dx; }
1288 | }
1289 | }
1290 | else
1291 | {
1292 | e = dx - dy / 2;
1293 | while (y1-- >= y2)
1294 | for(; y1 >= y2; y1--, e += dx)
1295 | {
1296 | draw_pixel(x1, y1, rgb, z_order);
1297 | if (e>0) { x1--; e -= dy; }
1298 | }
1299 | }
1300 | }
1301 | }
1302 |
1303 | void c_surface::draw_rect(int x0, int y0, int x1, int y1, unsigned int rgb, unsigned int z_order, unsigned int size)
1304 | {
1305 | for (unsigned int offset = 0; offset < size; offset++)
1306 | {
1307 | draw_hline(x0 + offset, x1 - offset, y0 + offset, rgb, z_order);
1308 | draw_hline(x0 + offset, x1 - offset, y1 - offset, rgb, z_order);
1309 | draw_vline(x0 + offset, y0 + offset, y1 - offset, rgb, z_order);
1310 | draw_vline(x1 - offset, y0 + offset, y1 - offset, rgb, z_order);
1311 | }
1312 | }
1313 |
1314 | int c_surface::set_frame_layer_visible_rect(c_rect& rect, unsigned int z_order)
1315 | {
1316 | if (rect == m_frame_layers[z_order].visible_rect)
1317 | {
1318 | return 0;
1319 | }
1320 | if (rect.m_left < 0 || rect.m_left >= m_width ||
1321 | rect.m_right < 0 || rect.m_right >= m_width ||
1322 | rect.m_top < 0 || rect.m_top >= m_height ||
1323 | rect.m_bottom < 0 || rect.m_bottom >=m_height)
1324 | {
1325 | ASSERT(false);
1326 | return -1;
1327 | }
1328 | if (!(z_order > Z_ORDER_LEVEL_0 && z_order < Z_ORDER_LEVEL_MAX))
1329 | {
1330 | ASSERT(false);
1331 | return -2;
1332 | }
1333 | if (z_order < m_top_zorder)
1334 | {
1335 | ASSERT(false);
1336 | return -3;
1337 | }
1338 | m_top_zorder = (Z_ORDER_LEVEL)z_order;
1339 |
1340 | c_rect old_rect = m_frame_layers[z_order].visible_rect;
1341 | //Recover the lower layer
1342 | int src_zorder = (Z_ORDER_LEVEL)(z_order - 1);
1343 | int display_width = m_display->get_width();
1344 | int display_height = m_display->get_height();
1345 |
1346 | for (int y = old_rect.m_top; y <= old_rect.m_bottom; y++)
1347 | {
1348 | for (int x = old_rect.m_left; x <= old_rect.m_right; x++)
1349 | {
1350 | if (!rect.PtInRect(x, y))
1351 | {
1352 | unsigned int rgb = ((unsigned short*)(m_frame_layers[src_zorder].fb))[x + y * m_width];
1353 | draw_pixel_on_fb(x, y, GL_RGB_16_to_32(rgb));
1354 | }
1355 | }
1356 | }
1357 |
1358 | m_frame_layers[z_order].visible_rect = rect;
1359 | if (rect.IsEmpty())
1360 | {
1361 | m_top_zorder = (Z_ORDER_LEVEL)(z_order - 1);
1362 | }
1363 | return 0;
1364 | }
1365 |
1366 | int c_surface::flush_scrren(int left, int top, int right, int bottom)
1367 | {
1368 | if(left < 0 || left >= m_width || right < 0 || right >= m_width ||
1369 | top < 0 || top >= m_height || bottom < 0 || bottom >= m_height)
1370 | {
1371 | ASSERT(false);
1372 | }
1373 |
1374 | if(!m_is_active || (0 == m_phy_fb) || (0 == m_fb))
1375 | {
1376 | return -1;
1377 | }
1378 |
1379 | int display_width = m_display->get_width();
1380 | int display_height = m_display->get_height();
1381 |
1382 | left = (left >= display_width) ? (display_width - 1) : left;
1383 | right = (right >= display_width) ? (display_width - 1) : right;
1384 | top = (top >= display_height) ? (display_height - 1) : top;
1385 | bottom = (bottom >= display_height) ? (display_height - 1) : bottom;
1386 |
1387 | for (int y = top; y < bottom; y++)
1388 | {
1389 | void* s_addr = (char*)m_fb + ((y * m_width + left) * m_color_bytes);
1390 | void* d_addr = (char*)m_phy_fb + ((y * display_width + left) * m_color_bytes);
1391 | memcpy(d_addr, s_addr, (right - left) * m_color_bytes);
1392 | }
1393 | *m_phy_write_index = *m_phy_write_index + 1;
1394 | return 0;
1395 | }
1396 |
1397 | bool c_surface::is_valid(c_rect rect)
1398 | {
1399 | if (rect.m_left < 0 || rect.m_top < 0)
1400 | {
1401 | return false;
1402 | }
1403 |
1404 | if (rect.m_right >= m_width || rect.m_bottom >= m_height)
1405 | {
1406 | return false;
1407 | }
1408 | return true;
1409 | }
1410 |
1411 | //////////////////////////////////////////////////////////////////////////////////////
1412 | void c_surface_no_fb::fill_rect_on_fb(int x0, int y0, int x1, int y1, unsigned int rgb)
1413 | {
1414 | if (!m_gfx_op)
1415 | {
1416 | return;
1417 | }
1418 | if (m_gfx_op->fill_rect)
1419 | {
1420 | return m_gfx_op->fill_rect(x0, y0, x1, y1, rgb);
1421 | }
1422 |
1423 | if (m_gfx_op->draw_pixel && m_is_active)
1424 | {
1425 | for (int y = y0; y <= y1; y++)
1426 | {
1427 | for (int x = x0; x <= x1; x++)
1428 | {
1429 | m_gfx_op->draw_pixel(x, y, rgb);
1430 | }
1431 | }
1432 | }
1433 |
1434 | if (!m_fb) { return; }
1435 | if(m_color_bytes == 4)
1436 | {
1437 | unsigned int *fb;
1438 | for (int y = y0; y <= y1; y++)
1439 | {
1440 | fb = &((unsigned int*)m_fb)[y0 * m_width + x0];
1441 | for (int x = x0; x <= x1; x++)
1442 | {
1443 | *fb++ = rgb;
1444 | }
1445 | }
1446 | }
1447 | else if (m_color_bytes == 2)
1448 | {
1449 | unsigned short *fb;
1450 | rgb = GL_RGB_32_to_16(rgb);
1451 | for (int y = y0; y <= y1; y++)
1452 | {
1453 | fb = &((unsigned short*)m_fb)[y0 * m_width + x0];
1454 | for (int x = x0; x <= x1; x++)
1455 | {
1456 | *fb++ = rgb;
1457 | }
1458 | }
1459 | }
1460 | }
1461 |
1462 | void c_surface_no_fb::draw_pixel_on_fb(int x, int y, unsigned int rgb)
1463 | {
1464 | if (m_gfx_op && m_gfx_op->draw_pixel && m_is_active)
1465 | {
1466 | m_gfx_op->draw_pixel(x, y, rgb);
1467 | }
1468 |
1469 | if (!m_fb) { return; }
1470 | if (m_color_bytes == 4)
1471 | {
1472 | ((unsigned int*)m_fb)[y * m_width + x] = rgb;
1473 | }
1474 | else if (m_color_bytes == 2)
1475 | {
1476 | ((unsigned short*)m_fb)[y * m_width + x] = GL_RGB_32_to_16(rgb);
1477 | }
1478 | }
1479 |
1480 | static const FONT_INFO* s_font_map[FONT_MAX];
1481 | static const BITMAP_INFO* s_bmp_map[BITMAP_MAX];
1482 | static unsigned int s_color_map[COLOR_MAX];
1483 |
1484 | int c_theme::add_font(FONT_TYPE index, const FONT_INFO* font)
1485 | {
1486 | if (index >= FONT_MAX)
1487 | {
1488 | ASSERT(false);
1489 | return -1;
1490 | }
1491 | s_font_map[index] = font;
1492 | return 0;
1493 | }
1494 |
1495 | const FONT_INFO* c_theme::get_font(FONT_TYPE index)
1496 | {
1497 | if (index >= FONT_MAX)
1498 | {
1499 | ASSERT(false);
1500 | return 0;
1501 | }
1502 | return s_font_map[index];
1503 | }
1504 |
1505 | int c_theme::add_bitmap(BITMAP_TYPE index, const BITMAP_INFO* bmp)
1506 | {
1507 | if (index >= BITMAP_MAX)
1508 | {
1509 | ASSERT(false);
1510 | return -1;
1511 | }
1512 | s_bmp_map[index] = bmp;
1513 | return 0;
1514 | }
1515 |
1516 | const BITMAP_INFO* c_theme::get_bmp(BITMAP_TYPE index)
1517 | {
1518 | if (index >= BITMAP_MAX)
1519 | {
1520 | ASSERT(false);
1521 | return 0;
1522 | }
1523 | return s_bmp_map[index];
1524 | }
1525 |
1526 | int c_theme::add_color(COLOR_TYPE index, const unsigned int color)
1527 | {
1528 | if (index >= COLOR_MAX)
1529 | {
1530 | ASSERT(false);
1531 | return -1;
1532 | }
1533 | s_color_map[index] = color;
1534 | return 0;
1535 | }
1536 |
1537 | const unsigned int c_theme::get_color(COLOR_TYPE index)
1538 | {
1539 | if (index >= COLOR_MAX)
1540 | {
1541 | ASSERT(false);
1542 | return 0;
1543 | }
1544 | return s_color_map[index];
1545 | }
1546 |
1547 | c_wnd::c_wnd(): m_status(STATUS_NORMAL), m_attr(ATTR_VISIBLE), m_parent(0), m_top_child(0), m_prev_sibling(0), m_next_sibling(0),
1548 | m_str(0), m_font_color(0), m_bg_color(0), m_resource_id(0), m_z_order(Z_ORDER_LEVEL_0), m_focus_child(0), m_surface(0)
1549 | {
1550 | m_attr = (WND_ATTRIBUTION)(ATTR_VISIBLE | ATTR_FOCUS);
1551 | }
1552 |
1553 | int c_wnd::connect(c_wnd *parent, unsigned short resource_id, const char* str,
1554 | short x, short y, short width, short height, WND_TREE* p_child_tree )
1555 | {
1556 | if(0 == resource_id)
1557 | {
1558 | ASSERT(false);
1559 | return -1;
1560 | }
1561 |
1562 | m_resource_id = resource_id;
1563 | set_str(str);
1564 | m_parent = parent;
1565 | m_status = STATUS_NORMAL;
1566 |
1567 | if (parent)
1568 | {
1569 | m_z_order = parent->m_z_order;
1570 | m_surface = parent->m_surface;
1571 | }
1572 | if(0 == m_surface)
1573 | {
1574 | ASSERT(false);
1575 | return -2;
1576 | }
1577 |
1578 | /* (cs.x = x * 1024 / 768) for 1027*768=>800*600 quickly*/
1579 | m_wnd_rect.m_left = x;
1580 | m_wnd_rect.m_top = y;
1581 | m_wnd_rect.m_right = (x + width - 1);
1582 | m_wnd_rect.m_bottom = (y + height - 1);
1583 |
1584 | c_rect rect;
1585 | get_screen_rect(rect);
1586 | ASSERT(m_surface->is_valid(rect));
1587 |
1588 | pre_create_wnd();
1589 |
1590 | if ( 0 != parent )
1591 | {
1592 | parent->add_child_2_tail(this);
1593 | }
1594 |
1595 | if (load_child_wnd(p_child_tree) >= 0)
1596 | {
1597 | load_cmd_msg();
1598 | on_init_children();
1599 | }
1600 | return 0;
1601 | }
1602 |
1603 | int c_wnd::load_child_wnd(WND_TREE *p_child_tree)
1604 | {
1605 | if (0 == p_child_tree)
1606 | {
1607 | return 0;
1608 | }
1609 | int sum = 0;
1610 |
1611 | WND_TREE* p_cur = p_child_tree;
1612 | while(p_cur->p_wnd)
1613 | {
1614 | if (0 != p_cur->p_wnd->m_resource_id)
1615 | {//This wnd has been used! Do not share!
1616 | ASSERT(false);
1617 | return -1;
1618 | }
1619 | else
1620 | {
1621 | p_cur->p_wnd->connect(this, p_cur->resource_id, p_cur->str,
1622 | p_cur->x, p_cur->y, p_cur->width, p_cur->height,p_cur->p_child_tree);
1623 | }
1624 | p_cur++;
1625 | sum++;
1626 | }
1627 | return sum;
1628 | }
1629 |
1630 | c_wnd* c_wnd::connect_clone(c_wnd *parent, unsigned short resource_id, const char* str,
1631 | short x, short y, short width, short height, WND_TREE* p_child_tree )
1632 | {
1633 | if(0 == resource_id)
1634 | {
1635 | ASSERT(false);
1636 | return 0;
1637 | }
1638 |
1639 | c_wnd* wnd = clone();
1640 | wnd->m_resource_id = resource_id;
1641 | wnd->set_str(str);
1642 | wnd->m_parent = parent;
1643 | wnd->m_status = STATUS_NORMAL;
1644 |
1645 | if (parent)
1646 | {
1647 | wnd->m_z_order = parent->m_z_order;
1648 | wnd->m_surface = parent->m_surface;
1649 | }
1650 | else
1651 | {
1652 | wnd->m_surface = m_surface;
1653 | }
1654 | if(0 == wnd->m_surface)
1655 | {
1656 | ASSERT(false);
1657 | return 0;
1658 | }
1659 |
1660 | /* (cs.x = x * 1024 / 768) for 1027*768=>800*600 quickly*/
1661 | wnd->m_wnd_rect.m_left = x;
1662 | wnd->m_wnd_rect.m_top = y;
1663 | wnd->m_wnd_rect.m_right = (x + width - 1);
1664 | wnd->m_wnd_rect.m_bottom = (y + height - 1);
1665 |
1666 | c_rect rect;
1667 | wnd->get_screen_rect(rect);
1668 | ASSERT(wnd->m_surface->is_valid(rect));
1669 |
1670 | wnd->pre_create_wnd();
1671 |
1672 | if ( 0 != parent )
1673 | {
1674 | parent->add_child_2_tail(wnd);
1675 | }
1676 |
1677 | if (wnd->load_clone_child_wnd(p_child_tree) >= 0)
1678 | {
1679 | wnd->load_cmd_msg();
1680 | wnd->on_init_children();
1681 | }
1682 | return wnd;
1683 | }
1684 |
1685 | int c_wnd::load_clone_child_wnd(WND_TREE *p_child_tree)
1686 | {
1687 | if (0 == p_child_tree)
1688 | {
1689 | return 0;
1690 | }
1691 | int sum = 0;
1692 |
1693 | WND_TREE* p_cur = p_child_tree;
1694 | while(p_cur->p_wnd)
1695 | {
1696 | p_cur->p_wnd->connect_clone(this, p_cur->resource_id, p_cur->str,
1697 | p_cur->x, p_cur->y, p_cur->width, p_cur->height,p_cur->p_child_tree);
1698 | p_cur++;
1699 | sum++;
1700 | }
1701 | return sum;
1702 | }
1703 |
1704 | void c_wnd::disconnect()
1705 | {
1706 | if (0 == m_resource_id)
1707 | {
1708 | return;
1709 | }
1710 |
1711 | if (0 != m_top_child)
1712 | {
1713 | c_wnd *child = m_top_child;
1714 | c_wnd *next_child = 0;
1715 |
1716 | while (child)
1717 | {
1718 | next_child = child->m_next_sibling;
1719 | child->disconnect();
1720 | child = next_child;
1721 | }
1722 | }
1723 |
1724 | if (0 != m_parent)
1725 | {
1726 | m_parent->unlink_child(this);
1727 | }
1728 | m_focus_child = 0;
1729 | m_resource_id = 0;
1730 | }
1731 |
1732 | c_wnd* c_wnd::get_wnd_ptr(unsigned short id) const
1733 | {
1734 | c_wnd *child = m_top_child;
1735 |
1736 | while ( child )
1737 | {
1738 | if ( child->get_id() == id )
1739 | {
1740 | break;
1741 | }
1742 |
1743 | child = child->m_next_sibling;
1744 | }
1745 |
1746 | return child;
1747 | }
1748 |
1749 | void c_wnd::set_attr(WND_ATTRIBUTION attr)
1750 | {
1751 | m_attr = attr;
1752 |
1753 | if ( ATTR_DISABLED == (attr & ATTR_DISABLED) )
1754 | {
1755 | m_status = STATUS_DISABLED;
1756 | }
1757 | else
1758 | {
1759 | if (m_status == STATUS_DISABLED)
1760 | {
1761 | m_status = STATUS_NORMAL;
1762 | }
1763 | }
1764 | }
1765 |
1766 | int c_wnd::is_focus_wnd() const
1767 | {
1768 | if ( (m_attr & ATTR_VISIBLE)
1769 | && !(m_attr & ATTR_DISABLED)
1770 | && (m_attr & ATTR_FOCUS))
1771 | {
1772 | return true;
1773 | }
1774 | else
1775 | {
1776 | return false;
1777 | }
1778 | }
1779 |
1780 | void c_wnd::set_wnd_pos(short x, short y, short width, short height)
1781 | {
1782 | m_wnd_rect.m_left = x;
1783 | m_wnd_rect.m_top = y;
1784 | m_wnd_rect.m_right = x + width - 1;
1785 | m_wnd_rect.m_bottom = y + height - 1;
1786 | }
1787 |
1788 | void c_wnd::get_wnd_rect(c_rect &rect) const
1789 | {
1790 | rect = m_wnd_rect;
1791 | }
1792 |
1793 | void c_wnd::get_screen_rect(c_rect &rect) const
1794 | {
1795 | rect.SetRect(0, 0, (m_wnd_rect.Width() - 1), (m_wnd_rect.Height() - 1));
1796 | wnd2screen(rect);
1797 | }
1798 |
1799 | void c_wnd::wnd2screen(int &x, int &y) const
1800 | {
1801 | c_wnd *parent = m_parent;
1802 | c_rect rect;
1803 |
1804 | x += m_wnd_rect.m_left;
1805 | y += m_wnd_rect.m_top;
1806 |
1807 | while ( 0 != parent )
1808 | {
1809 | parent->get_wnd_rect(rect);
1810 | x += rect.m_left;
1811 | y += rect.m_top;
1812 |
1813 | parent = parent->m_parent;
1814 | }
1815 | }
1816 |
1817 | void c_wnd::wnd2screen(c_rect &rect) const
1818 | {
1819 | int l = rect.m_left;
1820 | int t = rect.m_top;
1821 | wnd2screen(l, t);
1822 |
1823 | int r = (l + rect.Width() - 1);
1824 | int b = (t + rect.Height() - 1);
1825 | rect.SetRect(l, t, r, b);
1826 | }
1827 |
1828 | void c_wnd::screen2wnd(short &x, short &y) const
1829 | {
1830 | c_wnd *parent = m_parent;
1831 | c_rect rect;
1832 |
1833 | x -= m_wnd_rect.m_left;
1834 | y -= m_wnd_rect.m_top;
1835 |
1836 | while ( 0 != parent )
1837 | {
1838 | parent->get_wnd_rect(rect);
1839 | x -= rect.m_left;
1840 | y -= rect.m_top;
1841 | parent = parent->m_parent;
1842 | }
1843 | }
1844 |
1845 | void c_wnd::screen2wnd(c_rect &rect) const
1846 | {
1847 | short l = rect.m_left;
1848 | short t = rect.m_top;
1849 | screen2wnd(l, t);
1850 |
1851 | short r = l + rect.Width() - 1;
1852 | short b = t + rect.Height() - 1;
1853 | rect.SetRect(l, t, r, b);
1854 | }
1855 |
1856 | c_wnd* c_wnd::set_child_focus(c_wnd * focus_child)
1857 | {
1858 | ASSERT(0 != focus_child);
1859 | ASSERT(focus_child->m_parent == this);
1860 |
1861 | c_wnd *old_focus_child = m_focus_child;
1862 | if (focus_child->is_focus_wnd())
1863 | {
1864 | if (focus_child != old_focus_child )
1865 | {
1866 | if (old_focus_child)
1867 | {
1868 | old_focus_child->on_kill_focus();
1869 | }
1870 | m_focus_child = focus_child;
1871 |
1872 | if (m_parent)
1873 | {
1874 | m_parent->set_child_focus(this);
1875 | }
1876 | m_focus_child->on_focus();
1877 | }
1878 | }
1879 | return m_focus_child;
1880 | }
1881 |
1882 | void c_wnd::add_child_2_tail(c_wnd *child)
1883 | {
1884 | if( 0 == child )return;
1885 | if(child == get_wnd_ptr(child->m_resource_id))return;
1886 |
1887 | if ( 0 == m_top_child )
1888 | {
1889 | m_top_child = child;
1890 | child->m_prev_sibling = 0;
1891 | child->m_next_sibling = 0;
1892 | }
1893 | else
1894 | {
1895 | c_wnd *last_child = get_last_child();
1896 | if (0 == last_child)
1897 | {
1898 | ASSERT(false);
1899 | }
1900 | last_child->m_next_sibling = child;
1901 | child->m_prev_sibling = last_child;
1902 | child->m_next_sibling = 0;
1903 | }
1904 | }
1905 |
1906 | c_wnd* c_wnd::get_last_child() const
1907 | {
1908 | if ( 0 == m_top_child )
1909 | {
1910 | return 0;
1911 | }
1912 |
1913 | c_wnd *child = m_top_child;
1914 |
1915 | while ( child->m_next_sibling)
1916 | {
1917 | child = child->m_next_sibling;
1918 | }
1919 |
1920 | return child;
1921 | }
1922 |
1923 | int c_wnd::unlink_child(c_wnd *child)
1924 | {
1925 | if ((0 == child)
1926 | || (this != child->m_parent))
1927 | {
1928 | return -1;
1929 | }
1930 |
1931 | if (0 == m_top_child)
1932 | {
1933 | return -2;
1934 | }
1935 |
1936 | int find = false;
1937 |
1938 | c_wnd *tmp_child = m_top_child;
1939 | if (tmp_child == child)
1940 | {
1941 | m_top_child = child->m_next_sibling;
1942 | if (0 != child->m_next_sibling)
1943 | {
1944 | child->m_next_sibling->m_prev_sibling = 0;
1945 | }
1946 |
1947 | find = true;
1948 | }
1949 | else
1950 | {
1951 | while (tmp_child->m_next_sibling)
1952 | {
1953 | if (child == tmp_child->m_next_sibling)
1954 | {
1955 | tmp_child->m_next_sibling = child->m_next_sibling;
1956 | if (0 != child->m_next_sibling)
1957 | {
1958 | child->m_next_sibling->m_prev_sibling = tmp_child;
1959 | }
1960 |
1961 | find = true;
1962 | break;
1963 | }
1964 |
1965 | tmp_child = tmp_child->m_next_sibling;
1966 | }
1967 | }
1968 |
1969 | if (true == find)
1970 | {
1971 | if (m_focus_child == child)
1972 | {
1973 | m_focus_child = 0;
1974 | }
1975 |
1976 | child->m_next_sibling = 0;
1977 | child->m_prev_sibling = 0;
1978 | return 1;
1979 | }
1980 | else
1981 | {
1982 | return 0;
1983 | }
1984 | }
1985 |
1986 | void c_wnd::show_window()
1987 | {
1988 | if (ATTR_VISIBLE == (m_attr & ATTR_VISIBLE))
1989 | {
1990 | on_paint();
1991 | c_wnd *child = m_top_child;
1992 | if ( 0 != child )
1993 | {
1994 | while ( child )
1995 | {
1996 | child->show_window();
1997 | child = child->m_next_sibling;
1998 | }
1999 | }
2000 | }
2001 | }
2002 |
2003 | bool c_wnd::on_touch(int x, int y, TOUCH_ACTION action)
2004 | {
2005 | c_rect rect;
2006 | x -= m_wnd_rect.m_left;
2007 | y -= m_wnd_rect.m_top;
2008 | c_wnd* child = m_top_child;
2009 |
2010 | c_wnd* target_wnd = 0;
2011 | int target_z_order = Z_ORDER_LEVEL_0;
2012 |
2013 | while (child)
2014 | {
2015 | if (ATTR_VISIBLE == (child->m_attr & ATTR_VISIBLE))
2016 | {
2017 | child->get_wnd_rect(rect);
2018 | if (true == rect.PtInRect(x, y) || child->m_attr & ATTR_MODAL)
2019 | {
2020 | if (true == child->is_focus_wnd())
2021 | {
2022 | if (child->m_z_order >= target_z_order)
2023 | {
2024 | target_wnd = child;
2025 | target_z_order = child->m_z_order;
2026 | }
2027 | }
2028 | }
2029 | }
2030 | child = child->m_next_sibling;
2031 | }
2032 |
2033 | if (target_wnd == 0)
2034 | {
2035 | return false;
2036 | }
2037 | return target_wnd->on_touch(x, y, action);
2038 | }
2039 |
2040 | bool c_wnd::on_key(KEY_TYPE key)
2041 | {
2042 | ASSERT(key == KEY_FORWARD || key == KEY_BACKWARD || key == KEY_ENTER);
2043 |
2044 | // Find current focus wnd.
2045 | c_wnd* old_focus_wnd = m_focus_child;
2046 | while (m_focus_child && m_focus_child->m_focus_child)
2047 | {
2048 | old_focus_wnd = m_focus_child->m_focus_child;
2049 | }
2050 | if (old_focus_wnd && !old_focus_wnd->on_key(key))
2051 | {
2052 | return true;
2053 | }
2054 |
2055 | // Default moving focus(Default handle KEY_FOWARD/KEY_BACKWARD)
2056 | if (key == KEY_ENTER)
2057 | {
2058 | return true;
2059 | }
2060 | if (!old_focus_wnd)
2061 | {// No current focus wnd, new one.
2062 | c_wnd *child = m_top_child;
2063 | c_wnd *new_focus_wnd = 0;
2064 | while (child)
2065 | {
2066 | if (ATTR_VISIBLE == (child->m_attr & ATTR_VISIBLE))
2067 | {
2068 | if (true == child->is_focus_wnd())
2069 | {
2070 | new_focus_wnd = child;
2071 | new_focus_wnd->m_parent->set_child_focus(new_focus_wnd);
2072 | child = child->m_top_child;
2073 | continue;
2074 | }
2075 | }
2076 | child = child->m_next_sibling;
2077 | }
2078 | return true;
2079 | }
2080 |
2081 | // Move focus from old wnd to next wnd
2082 | c_wnd* next_focus_wnd = (key == KEY_FORWARD) ? old_focus_wnd->m_next_sibling : old_focus_wnd->m_prev_sibling;
2083 | while (next_focus_wnd && (!next_focus_wnd->is_focus_wnd()))
2084 | {// Search neighbor of old focus wnd
2085 | next_focus_wnd = (key == KEY_FORWARD) ? next_focus_wnd->m_next_sibling : next_focus_wnd->m_prev_sibling;
2086 | }
2087 | if (!next_focus_wnd)
2088 | {// Search whole brother wnd
2089 | next_focus_wnd = (key == KEY_FORWARD) ? old_focus_wnd->m_parent->m_top_child : old_focus_wnd->m_parent->get_last_child();
2090 | while (next_focus_wnd && (!next_focus_wnd->is_focus_wnd()))
2091 | {
2092 | next_focus_wnd = (key == KEY_FORWARD) ? next_focus_wnd->m_next_sibling : next_focus_wnd->m_prev_sibling;
2093 | }
2094 | }
2095 | if (next_focus_wnd)
2096 | {
2097 | next_focus_wnd->m_parent->set_child_focus(next_focus_wnd);
2098 | }
2099 | return true;
2100 | }
2101 |
2102 | void c_wnd::notify_parent(unsigned int msg_id, unsigned int ctrl_id, int param)
2103 | {
2104 | if (!m_parent)
2105 | {
2106 | return;
2107 | }
2108 | const GL_MSG_ENTRY* entry = m_parent->FindMsgEntry(m_parent->GetMSgEntries(), MSG_TYPE_WND, msg_id, ctrl_id);
2109 | if (0 == entry)
2110 | {
2111 | return;
2112 | }
2113 |
2114 | MSGFUNCS msg_funcs;
2115 | msg_funcs.func = entry->func;
2116 |
2117 | switch (entry->callbackType)
2118 | {
2119 | case MSG_CALLBACK_VV:
2120 | (m_parent->*msg_funcs.func)();
2121 | break;
2122 | case MSG_CALLBACK_VVL:
2123 | (m_parent->*msg_funcs.func_vvl)(param);
2124 | break;
2125 | case MSG_CALLBACK_VWV:
2126 | (m_parent->*msg_funcs.func_vwv)(ctrl_id);
2127 | break;
2128 | case MSG_CALLBACK_VWL:
2129 | (m_parent->*msg_funcs.func_vwl)(ctrl_id, param);
2130 | break;
2131 | default:
2132 | ASSERT(false);
2133 | break;
2134 | }
2135 | }
2136 |
2137 | #define BUFFER_LEN 16
2138 | unsigned char s_utf8_length_table[256] =
2139 | {
2140 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2141 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2142 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2143 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2144 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2145 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2146 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2147 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2148 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2149 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2150 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2151 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2152 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2153 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2154 | 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2155 | 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1
2156 | };
2157 |
2158 | inline static int get_utf8_code(const char* s, unsigned int& output_utf8_code)
2159 | {
2160 | unsigned char* us = (unsigned char*)s;
2161 | int utf8_bytes = s_utf8_length_table[*us];
2162 | switch (utf8_bytes)
2163 | {
2164 | case 1:
2165 | output_utf8_code = *us;
2166 | break;
2167 | case 2:
2168 | output_utf8_code = (*us << 8) | (*(us + 1));
2169 | break;
2170 | case 3:
2171 | output_utf8_code = (*us << 16) | ((*(us + 1)) << 8) | *(us + 2);
2172 | break;
2173 | case 4:
2174 | output_utf8_code = (*us << 24) | ((*(us + 1)) << 16) | (*(us + 2) << 8) | *(us + 3);
2175 | break;
2176 | default:
2177 | ASSERT(false);
2178 | break;
2179 | }
2180 | return utf8_bytes;
2181 | }
2182 |
2183 | void c_word::draw_value_in_rect(c_surface* surface, int z_order, int value, int dot_position, c_rect rect, const FONT_INFO* font, unsigned int font_color, unsigned int bg_color, unsigned int align_type)
2184 | {
2185 | char buf[BUFFER_LEN];
2186 | value_2_string(value, dot_position, buf, BUFFER_LEN);
2187 | draw_string_in_rect(surface, z_order, buf, rect, font, font_color, bg_color, align_type);
2188 | }
2189 |
2190 | void c_word::draw_value(c_surface* surface, int z_order, int value, int dot_position, int x, int y, const FONT_INFO* font, unsigned int font_color, unsigned int bg_color, unsigned int align_type)
2191 | {
2192 | char buf[BUFFER_LEN];
2193 | value_2_string(value, dot_position, buf, BUFFER_LEN);
2194 | draw_string(surface, z_order, buf, x, y, font, font_color, bg_color, align_type);
2195 | }
2196 |
2197 | void c_word::draw_string_in_rect(c_surface* surface, int z_order, const char *s, c_rect rect, const FONT_INFO* font, unsigned int font_color, unsigned int bg_color, unsigned int align_type)
2198 | {
2199 | if(0 == s)
2200 | {
2201 | return;
2202 | }
2203 | int x, y;
2204 | get_string_pos(s, font, rect, align_type, x, y);
2205 | draw_string(surface, z_order, s, rect.m_left + x, rect.m_top + y, font, font_color, bg_color, ALIGN_LEFT);
2206 | }
2207 |
2208 | void c_word::draw_string(c_surface* surface, int z_order, const char *s, int x, int y, const FONT_INFO* font, unsigned int font_color, unsigned int bg_color, unsigned int align_type)
2209 | {
2210 | if (0 == s)
2211 | {
2212 | return;
2213 | }
2214 |
2215 | int offset = 0;
2216 | unsigned int utf8_code;
2217 | while (*s)
2218 | {
2219 | s += get_utf8_code(s, utf8_code);
2220 | offset += draw_single_char(surface, z_order, utf8_code, (x + offset), y, font, font_color, bg_color);
2221 | }
2222 | }
2223 |
2224 | void c_word::value_2_string(int value, int dot_position, char* buf, int len)
2225 | {
2226 | memset(buf, 0, len);
2227 | switch (dot_position)
2228 | {
2229 | case 0:
2230 | sprintf(buf, "%d", value);
2231 | break;
2232 | case 1:
2233 | sprintf(buf, "%.1f", value*1.0 / 10);
2234 | break;
2235 | case 2:
2236 | sprintf(buf, "%.2f", value*1.0 / 100);
2237 | break;
2238 | case 3:
2239 | sprintf(buf, "%.3f", value*1.0 / 1000);
2240 | break;
2241 | default:
2242 | ASSERT(false);
2243 | break;
2244 | }
2245 | }
2246 |
2247 | const LATTICE* c_word::get_lattice(const FONT_INFO* font, unsigned int utf8_code)
2248 | {
2249 | int first = 0;
2250 | int last = font->count - 1;
2251 | int middle = (first + last) / 2;
2252 |
2253 | while (first <= last)
2254 | {
2255 | if (font->lattice_array[middle].utf8_code < utf8_code)
2256 | first = middle + 1;
2257 | else if (font->lattice_array[middle].utf8_code == utf8_code)
2258 | {
2259 | return &font->lattice_array[middle];
2260 | }
2261 | else
2262 | {
2263 | last = middle - 1;
2264 | }
2265 | middle = (first + last) / 2;
2266 | }
2267 | return 0;
2268 | }
2269 |
2270 | int c_word::draw_single_char(c_surface* surface, int z_order, unsigned int utf8_code, int x, int y, const FONT_INFO* font, unsigned int font_color, unsigned int bg_color)
2271 | {
2272 | unsigned int error_color = 0xFFFFFFFF;
2273 | if (font)
2274 | {
2275 | const LATTICE* p_lattice = get_lattice(font, utf8_code);
2276 | if (p_lattice)
2277 | {
2278 | draw_lattice(surface, z_order, x, y, p_lattice->width, font->height, p_lattice->p_data, font_color, bg_color);
2279 | return p_lattice->width;
2280 | }
2281 | }
2282 | else
2283 | {
2284 | error_color = GL_RGB(255, 0, 0);
2285 | }
2286 |
2287 | //lattice/font not found, draw "X"
2288 | int len = 16;
2289 | for (int y_ = 0; y_ < len; y_++)
2290 | {
2291 | for (int x_ = 0; x_ < len; x_++)
2292 | {
2293 | int diff = (x_ - y_);
2294 | int sum = (x_ + y_);
2295 | (diff == 0 || diff == -1 || diff == 1 || sum == len || sum == (len - 1) || sum == (len + 1)) ?
2296 | surface->draw_pixel((x + x_), (y + y_), error_color, z_order) : surface->draw_pixel((x + x_), (y + y_), 0, z_order);
2297 | }
2298 | }
2299 | return len;
2300 | }
2301 |
2302 | void c_word::draw_lattice(c_surface* surface, int z_order, int x, int y, int width, int height,
2303 | const unsigned char* p_data, unsigned int font_color, unsigned int bg_color)
2304 | {
2305 | unsigned int r, g, b, rgb;
2306 | unsigned char blk_value = *p_data++;
2307 | unsigned char blk_cnt = *p_data++;
2308 | b = (GL_RGB_B(font_color) * blk_value + GL_RGB_B(bg_color) * (255 - blk_value)) >> 8;
2309 | g = (GL_RGB_G(font_color) * blk_value + GL_RGB_G(bg_color) * (255 - blk_value)) >> 8;
2310 | r = (GL_RGB_R(font_color) * blk_value + GL_RGB_R(bg_color) * (255 - blk_value)) >> 8;
2311 | rgb = GL_RGB(r, g, b);
2312 | for (int y_ = 0; y_ < height; y_++)
2313 | {
2314 | for (int x_ = 0; x_ < width; x_++)
2315 | {
2316 | ASSERT(blk_cnt);
2317 | if (0x00 == blk_value)
2318 | {
2319 | if (GL_ARGB_A(bg_color))
2320 | {
2321 | surface->draw_pixel(x + x_, y + y_, bg_color, z_order);
2322 | }
2323 | }
2324 | else
2325 | {
2326 | surface->draw_pixel((x + x_), (y + y_), rgb, z_order);
2327 | }
2328 | if (--blk_cnt == 0)
2329 | {//reload new block
2330 | blk_value = *p_data++;
2331 | blk_cnt = *p_data++;
2332 | b = (GL_RGB_B(font_color) * blk_value + GL_RGB_B(bg_color) * (255 - blk_value)) >> 8;
2333 | g = (GL_RGB_G(font_color) * blk_value + GL_RGB_G(bg_color) * (255 - blk_value)) >> 8;
2334 | r = (GL_RGB_R(font_color) * blk_value + GL_RGB_R(bg_color) * (255 - blk_value)) >> 8;
2335 | rgb = GL_RGB(r, g, b);
2336 | }
2337 | }
2338 | }
2339 | }
2340 |
2341 | int c_word::get_str_size(const char *s, const FONT_INFO* font, int& width, int& height)
2342 | {
2343 | if(0 == s || 0 == font)
2344 | {
2345 | width = height = 0;
2346 | return -1;
2347 | }
2348 |
2349 | int lattice_width = 0;
2350 | unsigned int utf8_code;
2351 | int utf8_bytes;
2352 | while (*s)
2353 | {
2354 | utf8_bytes = get_utf8_code(s, utf8_code);
2355 | const LATTICE* p_lattice = get_lattice(font, utf8_code);
2356 | lattice_width += p_lattice?p_lattice->width:font->height;
2357 | s += utf8_bytes;
2358 | }
2359 | width = lattice_width;
2360 | height = font->height;
2361 | return 0;
2362 | }
2363 |
2364 | void c_word::get_string_pos(const char *s, const FONT_INFO* font, c_rect rect, unsigned int align_type, int &x, int &y)
2365 | {
2366 | int x_size, y_size;
2367 | get_str_size(s, font, x_size, y_size);
2368 |
2369 | int height = rect.m_bottom - rect.m_top + 1;
2370 | int width = rect.m_right - rect.m_left + 1;
2371 |
2372 | x = y = 0;
2373 |
2374 | switch (align_type & ALIGN_HMASK)
2375 | {
2376 | case ALIGN_HCENTER:
2377 | //m_text_org_x=0
2378 | if (width > x_size)
2379 | {
2380 | x = (width - x_size)/2;
2381 | }
2382 | break;
2383 |
2384 | case ALIGN_LEFT:
2385 | x = 0;
2386 | break;
2387 |
2388 | case ALIGN_RIGHT:
2389 | //m_text_org_x=0
2390 | if (width > x_size)
2391 | {
2392 | x = width - x_size;
2393 | }
2394 | break;
2395 |
2396 | default:
2397 | ASSERT(0);
2398 | break;
2399 | }
2400 |
2401 | switch (align_type & ALIGN_VMASK)
2402 | {
2403 | case ALIGN_VCENTER:
2404 | //m_text_org_y=0
2405 | if (height > y_size)
2406 | {
2407 | y = (height - y_size)/2;
2408 | }
2409 | break;
2410 |
2411 | case ALIGN_TOP:
2412 | y = 0;
2413 | break;
2414 |
2415 | case ALIGN_BOTTOM:
2416 | //m_text_org_y=0
2417 | if (height > y_size)
2418 | {
2419 | y = height - y_size;
2420 | }
2421 | break;
2422 |
2423 | default:
2424 | ASSERT(0);
2425 | break;
2426 | }
2427 | }
2428 |
2429 | static void(*do_assert)(const char* file, int line);
2430 | static void(*do_log_out)(const char* log);
2431 | void register_debug_function(void(*my_assert)(const char* file, int line), void(*my_log_out)(const char* log))
2432 | {
2433 | do_assert = my_assert;
2434 | do_log_out = my_log_out;
2435 | }
2436 |
2437 | void _assert(const char* file, int line)
2438 | {
2439 | if(do_assert)
2440 | {
2441 | do_assert(file, line);
2442 | }
2443 | while(1);
2444 | }
2445 |
2446 | void log_out(const char* log)
2447 | {
2448 | if (do_log_out)
2449 | {
2450 | do_log_out(log);
2451 | }
2452 | }
2453 |
2454 | long get_time_in_second()
2455 | {
2456 | return 0;
2457 | }
2458 |
2459 | T_TIME second_to_day(long second)
2460 | {
2461 | T_TIME ret = {0};
2462 | return ret;
2463 | }
2464 |
2465 | T_TIME get_time()
2466 | {
2467 | T_TIME ret = {0};
2468 | return ret;
2469 | }
2470 |
2471 | void start_real_timer(void (*func)(void* arg))
2472 | {
2473 | log_out("Not support now");
2474 | }
2475 |
2476 | void register_timer(int milli_second, void func(void* ptmr, void* parg))
2477 | {
2478 | log_out("Not support now");
2479 | }
2480 |
2481 | unsigned int get_cur_thread_id()
2482 | {
2483 | log_out("Not support now");
2484 | return 0;
2485 | }
2486 |
2487 | void create_thread(unsigned long* thread_id, void* attr, void *(*start_routine) (void *), void* arg)
2488 | {
2489 | log_out("Not support now");
2490 | }
2491 |
2492 | extern "C" void delay_ms(unsigned short nms);
2493 | void thread_sleep(unsigned int milli_seconds)
2494 | {//MCU alway implemnet driver code in APP.
2495 | //delay_ms(milli_seconds);
2496 | }
2497 |
2498 | int build_bmp(const char *filename, unsigned int width, unsigned int height, unsigned char *data)
2499 | {
2500 | log_out("Not support now");
2501 | return 0;
2502 | }
2503 |
2504 | //////////////////////// start UI ////////////////////////
2505 | #define UI_WIDTH 240
2506 | #define UI_HEIGHT 320
2507 | #define EMITTER_X 120
2508 | #define EMITTER_Y 250
2509 | #define ACC_X 0
2510 | #define ACC_Y 1
2511 | #define PARTICAL_WITH 3
2512 | #define PARTICAL_HEIGHT 3
2513 |
2514 | static c_surface* s_surface;
2515 |
2516 | class c_particle {
2517 | public:
2518 | c_particle(){
2519 | initialize();
2520 | }
2521 | void initialize() {
2522 | m_x = EMITTER_X; m_y = EMITTER_Y;
2523 | m_x_velocity = (rand() % 7) - 3; m_y_velocity = -15 - (rand() % 4);
2524 | }
2525 | void move() {
2526 | s_surface->fill_rect(m_x, m_y, m_x + PARTICAL_WITH - 1, m_y + PARTICAL_HEIGHT - 1, GL_RGB(14, 31, 143), Z_ORDER_LEVEL_0);//clear previous image
2527 | m_x_velocity += ACC_X; m_y_velocity += ACC_Y;
2528 | m_x += m_x_velocity; m_y += m_y_velocity;
2529 | if (m_x < 0 || (m_x + PARTICAL_WITH - 1) >= UI_WIDTH || m_y < 0 || (m_y + PARTICAL_HEIGHT - 1) >= UI_HEIGHT) {
2530 | initialize();
2531 | }
2532 | }
2533 | void draw() {
2534 | int red = rand() % 5 * 63;
2535 | int green = rand() % 5 * 63;
2536 | int blue = rand() % 5 * 63;
2537 | s_surface->fill_rect(m_x, m_y, m_x + PARTICAL_WITH - 1, m_y + PARTICAL_HEIGHT - 1, GL_RGB(red, green, blue), Z_ORDER_LEVEL_0);//draw current image
2538 | }
2539 | int m_x, m_y, m_x_velocity, m_y_velocity;
2540 | };
2541 |
2542 | c_display* display;
2543 | c_particle particle_array[100];
2544 | void create_ui(void* phy_fb, int screen_width, int screen_height, int color_bytes, struct EXTERNAL_GFX_OP* gfx_op) {
2545 | display = new c_display(phy_fb, screen_width, screen_height, UI_WIDTH, UI_HEIGHT, color_bytes, 1, gfx_op);
2546 | s_surface = display->alloc_surface((void*)1, Z_ORDER_LEVEL_0);
2547 | s_surface->set_active(true);
2548 | s_surface->fill_rect(0, 0, UI_WIDTH - 1, UI_HEIGHT - 1, GL_RGB(14, 31, 143), Z_ORDER_LEVEL_0);
2549 | }
2550 |
2551 | ///////////////// WebAssembly Code /////////////////
2552 |
2553 | #include
2554 | #include
2555 |
2556 | #define WASM_EXPORT __attribute__((visibility("default")))
2557 |
2558 | /* External function that is implemented in JavaScript. */
2559 | extern "C" void drawGuiLitePixel(int x, int y, int color);
2560 | struct EXTERNAL_GFX_OP my_gfx_op;
2561 |
2562 | WASM_EXPORT
2563 | int main(int mode) {
2564 | switch(mode){
2565 | case 0:
2566 | create_ui(calloc(240 * 320, 4), 240, 320, 4, NULL);
2567 | break;
2568 | default:
2569 | my_gfx_op.draw_pixel = drawGuiLitePixel;
2570 | my_gfx_op.fill_rect = NULL;//gfx_fill_rect;
2571 | create_ui(NULL, 240, 320, 4, &my_gfx_op);
2572 | break;
2573 | }
2574 | printf("GuiLite ready\n");
2575 | }
2576 |
2577 | WASM_EXPORT
2578 | extern "C" unsigned char* updateHelloParticle(void) {
2579 | for (int i = 0; i < sizeof(particle_array)/sizeof(c_particle); i++) {
2580 | particle_array[i].move();
2581 | particle_array[i].draw();
2582 | }
2583 | return (unsigned char*)display->get_updated_fb(NULL, NULL);
2584 | }
2585 |
2586 | /* External function that is implemented in JavaScript. */
2587 | extern "C" void putc_js(char c);
2588 |
2589 | /* Basic implementation of the writev sys call. */
2590 | WASM_EXPORT
2591 | extern "C" size_t writev_c(int fd, const struct iovec *iov, int iovcnt) {
2592 | size_t cnt = 0;
2593 | for (int i = 0; i < iovcnt; i++) {
2594 | for (int j = 0; j < iov[i].iov_len; j++) {
2595 | putc_js(((char *)iov[i].iov_base)[j]);
2596 | }
2597 | cnt += iov[i].iov_len;
2598 | }
2599 | return cnt;
2600 | }
2601 |
--------------------------------------------------------------------------------
/HelloParticle/src/main.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/HelloParticle/src/main.js:
--------------------------------------------------------------------------------
1 | let wasm = '../out/main.wasm';
2 | let instance = null;
3 | let memoryStates = new WeakMap();
4 | let mode = 1
5 | let ctx
6 |
7 | function syscall(instance, n, args) {
8 | switch (n) {
9 | default:
10 | // console.log("Syscall " + n + " NYI.");
11 | break;
12 | case /* brk */ 45: return 0;
13 | case /* writev */ 146:
14 | return instance.exports.writev_c(args[0], args[1], args[2]);
15 | case /* mmap2 */ 192:
16 | // debugger;
17 | const memory = instance.exports.memory;
18 | let memoryState = memoryStates.get(instance);
19 | const requested = args[1];
20 | if (!memoryState) {
21 | memoryState = {
22 | object: memory,
23 | currentPosition: memory.buffer.byteLength,
24 | };
25 | memoryStates.set(instance, memoryState);
26 | }
27 | let cur = memoryState.currentPosition;
28 | if (cur + requested > memory.buffer.byteLength) {
29 | const need = Math.ceil((cur + requested - memory.buffer.byteLength) / 65536);
30 | memory.grow(need);
31 | }
32 | memoryState.currentPosition += requested;
33 | return cur;
34 | }
35 | }
36 |
37 | let s = "";
38 | fetch(wasm).then(response =>
39 | response.arrayBuffer()
40 | ).then(bytes =>
41 | WebAssembly.instantiate(bytes, {
42 | env: {
43 | __syscall0: function __syscall0(n) { return syscall(instance, n, []); },
44 | __syscall1: function __syscall1(n, a) { return syscall(instance, n, [a]); },
45 | __syscall2: function __syscall2(n, a, b) { return syscall(instance, n, [a, b]); },
46 | __syscall3: function __syscall3(n, a, b, c) { return syscall(instance, n, [a, b, c]); },
47 | __syscall4: function __syscall4(n, a, b, c, d) { return syscall(instance, n, [a, b, c, d]); },
48 | __syscall5: function __syscall5(n, a, b, c, d, e) { return syscall(instance, n, [a, b, c, d, e]); },
49 | __syscall6: function __syscall6(n, a, b, c, d, e, f) { return syscall(instance, n, [a, b, c, d, e, f]); },
50 |
51 | putc_js: function (c) {
52 | c = String.fromCharCode(c);
53 | if (c == "\n") {
54 | console.log(s);
55 | s = "";
56 | } else {
57 | s += c;
58 | }
59 | },
60 |
61 | drawGuiLitePixel: function (x, y, color) {
62 | ctx.fillStyle = 'rgb(' + ((color & 0xff0000) >> 16) + ', ' + ((color & 0xff00) >> 8) + ', ' + (color & 0xff) + ')'
63 | ctx.fillRect(x, y, 1, 1)
64 | }
65 | }
66 | })
67 | ).then(results => {
68 | var canvas = document.getElementById("Canvas")
69 | ctx = canvas.getContext("2d")
70 |
71 | instance = results.instance;
72 | instance.exports.main(mode);
73 |
74 | if(mode != 0) { // mode 1
75 | setInterval(function(){
76 | instance.exports.updateHelloParticle()
77 | }, 30);
78 | return;
79 | }
80 |
81 | // mode 0
82 | var buffer = new Uint8Array(instance.exports.memory.buffer)
83 | setInterval(function(){
84 | var pointer = instance.exports.updateHelloParticle()
85 | for(let y = 0; y < 320; y++) {
86 | for(let x = 0; x < 240; x++) {
87 | ctx.fillStyle = 'rgb(' + buffer[pointer + 2] + ', ' + buffer[pointer + 1] + ', ' + buffer[pointer] + ')'
88 | ctx.fillRect(x, y, 1, 1)
89 | pointer = pointer + 4
90 | }
91 | }
92 | }, 30);
93 | }).catch(console.error);
94 |
--------------------------------------------------------------------------------
/HelloWave/README.md:
--------------------------------------------------------------------------------
1 | # Hello World in C
2 |
3 | Level: *Advanced*
4 |
5 | This project prints `"Hello World"` using the well known C `printf` function. This function in turn uses several POSIX APIs that are implemented in JavaScript using DOM APIs.
6 |
7 | ### Project Overview
8 |
9 | * `main.c` - Imports `stdio.h` and calls `printf("Hello World")`.
10 | * `main.js` - Initializes a runtime environment for the WebAssembly module and implements the necessary WebAssembly imports.
11 |
12 | ### Things to Explore
13 |
14 | 1. Click Build to compile `main.c` file to `out/main.wasm`.
15 |
16 | 2. Open the `out/main.wasm` file and notice that there's quite a bit of code. This is somewhat surprising given that our program is so small. The vast majority of this code implements the `printf` function.
17 |
18 | 3. Notice the imports section, these are SysCalls. To get this WebAssembly module running you'll have to implement these functions first. However, note that these import names don't actually tell you what SysCalls are used, they are merely function stubs (one for each number of parameters).
19 |
20 | ```
21 | (import "env" "__syscall0" (func $env.__syscall0 (type $t2)))
22 | (import "env" "__syscall3" (func $env.__syscall3 (type $t5)))
23 | (import "env" "__syscall1" (func $env.__syscall1 (type $t8)))
24 | ...
25 | ```
26 |
27 | 4. To figure that out which SysCalls are being used, you'll have to run the module. I ran it and got `45`, `146` and `192`. You can figure out what these numbers mean by looking them up in the [Linux SysCall Reference](https://syscalls.kernelgrok.com/). They are [brk()](http://man7.org/linux/man-pages/man2/brk.2.html), [writev()](http://man7.org/linux/man-pages/man2/writev.2.html) and [mmap()](http://man7.org/linux/man-pages/man2/mmap2.2.html). To make this WebAssembly module run, you'll just have to implement a tiny Linux kernel in JavaScript, no biggie.
28 |
29 | 5. Take a look at `src/main.js`, this file emulates these basic SysCalls in JavaScript.
30 |
31 | 6. `brk()` can be stubbed to return `0`, which is the success error code. `brk()` is used to allocate more memory to a process. WebAssembly does handles memory differently, so there's no need to do special here.
32 |
33 | 7. `mmap2()` is used to request more memory within the process. In our example, it's implemented as a call to the WebAssembly `memory.grow()` function.
34 |
35 | 8. `writev()` is used to write data to files. Its signature is `writev(int fd, const struct iovec *iov, int iovcnt)`. We can ignore the `fd` file descriptor parameter, and focus on the `iov` structure. The problem here is that on the JavaScript side we have a hard time pulling the `struct iovec` abart. We could figure it out, but a neat hack is to call back into the WebAssembly module and have some C code unpack it for us.
36 |
37 | 9. Click Run
38 |
39 | ```
40 | Hello World
41 | ```
--------------------------------------------------------------------------------
/HelloWave/build.ts:
--------------------------------------------------------------------------------
1 | import * as gulp from "gulp";
2 | import { Service, project } from "@wasm/studio-utils";
3 |
4 | gulp.task("build", async () => {
5 | const data = await Service.compileFile(project.getFile("src/main.cpp"), "cpp", "wasm", "-g -O3");
6 | const outWasm = project.newFile("out/main.wasm", "wasm", true);
7 | outWasm.setData(data);
8 | });
9 |
10 | gulp.task("default", ["build"], async () => {});
11 |
--------------------------------------------------------------------------------
/HelloWave/out/main.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/idea4good/GuiLiteWeb/3d87779deeedd4af200a37968e7d9874d64598c8/HelloWave/out/main.wasm
--------------------------------------------------------------------------------
/HelloWave/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@wasm/hello_world_c",
3 | "description": "",
4 | "version": "1.0.0",
5 | "scripts": {
6 | "build": "gulp --gulpfile ./build.ts"
7 | },
8 | "devDependencies": {
9 | "@wasm/studio-utils": "*",
10 | "gulp": "~3.9.1",
11 | "ts-node": "~5.0.0",
12 | "typescript": "~2.7.2"
13 | },
14 | "wasmStudio": {
15 | "name": "Hello World in C",
16 | "description": "# Hello World in C\n\nPrint \\`Hello World\\` using a minimal POSIX API.\nLevel: *Advanced*\nTopics: Low-Level, Memory, Linux, System Calls",
17 | "icon": "c-lang-file-icon"
18 | }
19 | }
--------------------------------------------------------------------------------
/HelloWave/src/main.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/HelloWave/src/main.js:
--------------------------------------------------------------------------------
1 | let wasm = '../out/main.wasm';
2 | let instance = null;
3 | let memoryStates = new WeakMap();
4 | let mode = 1
5 | let ctx
6 |
7 | function syscall(instance, n, args) {
8 | switch (n) {
9 | default:
10 | // console.log("Syscall " + n + " NYI.");
11 | break;
12 | case /* brk */ 45: return 0;
13 | case /* writev */ 146:
14 | return instance.exports.writev_c(args[0], args[1], args[2]);
15 | case /* mmap2 */ 192:
16 | // debugger;
17 | const memory = instance.exports.memory;
18 | let memoryState = memoryStates.get(instance);
19 | const requested = args[1];
20 | if (!memoryState) {
21 | memoryState = {
22 | object: memory,
23 | currentPosition: memory.buffer.byteLength,
24 | };
25 | memoryStates.set(instance, memoryState);
26 | }
27 | let cur = memoryState.currentPosition;
28 | if (cur + requested > memory.buffer.byteLength) {
29 | const need = Math.ceil((cur + requested - memory.buffer.byteLength) / 65536);
30 | memory.grow(need);
31 | }
32 | memoryState.currentPosition += requested;
33 | return cur;
34 | }
35 | }
36 |
37 | let s = "";
38 | fetch(wasm).then(response =>
39 | response.arrayBuffer()
40 | ).then(bytes =>
41 | WebAssembly.instantiate(bytes, {
42 | env: {
43 | __syscall0: function __syscall0(n) { return syscall(instance, n, []); },
44 | __syscall1: function __syscall1(n, a) { return syscall(instance, n, [a]); },
45 | __syscall2: function __syscall2(n, a, b) { return syscall(instance, n, [a, b]); },
46 | __syscall3: function __syscall3(n, a, b, c) { return syscall(instance, n, [a, b, c]); },
47 | __syscall4: function __syscall4(n, a, b, c, d) { return syscall(instance, n, [a, b, c, d]); },
48 | __syscall5: function __syscall5(n, a, b, c, d, e) { return syscall(instance, n, [a, b, c, d, e]); },
49 | __syscall6: function __syscall6(n, a, b, c, d, e, f) { return syscall(instance, n, [a, b, c, d, e, f]); },
50 |
51 | putc_js: function (c) {
52 | c = String.fromCharCode(c);
53 | if (c == "\n") {
54 | console.log(s);
55 | s = "";
56 | } else {
57 | s += c;
58 | }
59 | },
60 |
61 | drawGuiLitePixel: function (x, y, color) {
62 | ctx.fillStyle = 'rgb(' + ((color & 0xff0000) >> 16) + ', ' + ((color & 0xff00) >> 8) + ', ' + (color & 0xff) + ')'
63 | ctx.fillRect(x, y, 1, 1)
64 | }
65 | }
66 | })
67 | ).then(results => {
68 | var canvas = document.getElementById("Canvas")
69 | ctx = canvas.getContext("2d")
70 |
71 | instance = results.instance;
72 | instance.exports.main(mode);
73 |
74 | if(mode != 0) { // mode 1
75 | setInterval(function(){
76 | instance.exports.updateHelloWave()
77 | }, 30);
78 | return;
79 | }
80 |
81 | // mode 0
82 | var buffer = new Uint8Array(instance.exports.memory.buffer)
83 | setInterval(function(){
84 | var pointer = instance.exports.updateHelloWave()
85 | for(let y = 0; y < 320; y++) {
86 | for(let x = 0; x < 240; x++) {
87 | ctx.fillStyle = 'rgb(' + buffer[pointer + 2] + ', ' + buffer[pointer + 1] + ', ' + buffer[pointer] + ')'
88 | ctx.fillRect(x, y, 1, 1)
89 | pointer = pointer + 4
90 | }
91 | }
92 | }, 30);
93 | }).catch(console.error);
94 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | # GuiLiteWeb
6 | - [GuiLite](https://github.com/idea4good/GuiLite) is the smallest GUI library with 5000 lines of C++ code, could run on **all platforms**(e.g, iOS, Android, Linux, Windows, macOS, Docker and **MCU with or without OS**).
7 | - GuiLiteWeb inject GuiLite samples into Web page
8 |
9 | ## CubeEx
10 | 
11 | - Inject HelloParticle & HelloWave into Cube
12 | - [Source code](CubeEx/main.js)
13 | - Run it by open "CubeEx/index.html" with Microsoft Edge
14 |
15 | ## HelloParticle
16 | - Inject Guilite Sample(HelloParticle) into Web page
17 | - Run it by open "HelloParticle/src/main.html" with Microsoft Edge
18 |
19 | ## HelloWave
20 | - Inject Guilite Sample(HelloWave) into Web page
21 | - Run it by open "HelloWave/src/main.html" with Microsoft Edge
22 |
23 | ## Tutorial: How GuiLite graphic work?
24 | 
25 | - This 3D programm is used to show how GuiLite multi-layers work.
26 | - [Video](https://www.youtube.com/watch?v=QzZJnU5KmDQ)
27 | - [Source code](Graphic/main.js)
28 | - Run it by open "Graphic/index.html" with Microsoft Edge
29 |
30 | ## Cube
31 | 
32 | - [Source code](Cube/main.js)
33 | - Run it by open "Cube/index.html" with Microsoft Edge
34 |
--------------------------------------------------------------------------------
/README_zh.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | # GuiLiteWeb
6 | - [GuiLite](https://gitee.com/idea4good/GuiLite)是最轻量,最简单,最稳定的GUI库,它只有5千行C++代码
7 | - GuiLiteWeb可以把GuiLite注入到网页中
8 |
9 | ## CubeEx
10 | 
11 | - Inject HelloParticle & HelloWave into Cube
12 | - [Source code](CubeEx/main.js)
13 | - Run it by open "CubeEx/index.html" with Microsoft Edge
14 |
15 | ## HelloParticle
16 | - Inject Guilite Sample(HelloParticle) into Web page
17 | - Run it by open "HelloParticle/src/main.html" with Microsoft Edge
18 |
19 | ## HelloWave
20 | - Inject Guilite Sample(HelloWave) into Web page
21 | - Run it by open "HelloWave/src/main.html" with Microsoft Edge
22 |
23 | ## 教程:GuiLite底层绘制原理
24 | 
25 | - 通过3D程序,解释GuiLite滑动,及多层叠加原理
26 | - [视频](https://v.youku.com/v_show/id_XNDI4ODE1ODcwOA)
27 | - [Source code](Graphic/main.js)
28 | - Run it by open "Graphic/index.html" with Microsoft Edge
29 |
30 | ## GuiLite 立方体
31 | 
32 | - [Source code](Cube/main.js)
33 |
--------------------------------------------------------------------------------
/doc/GuiLite3D.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/idea4good/GuiLiteWeb/3d87779deeedd4af200a37968e7d9874d64598c8/doc/GuiLite3D.gif
--------------------------------------------------------------------------------
/doc/GuiLiteCube.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/idea4good/GuiLiteWeb/3d87779deeedd4af200a37968e7d9874d64598c8/doc/GuiLiteCube.gif
--------------------------------------------------------------------------------
/doc/GuiLiteGraphic.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/idea4good/GuiLiteWeb/3d87779deeedd4af200a37968e7d9874d64598c8/doc/GuiLiteGraphic.gif
--------------------------------------------------------------------------------