├── .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 | Image 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 | ![GuiLiteCube](doc/GuiLite3D.gif) 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 | ![GuiLiteGraphic](doc/GuiLiteGraphic.gif) 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 | ![GuiLiteCube](doc/GuiLiteCube.gif) 32 | - [Source code](Cube/main.js) 33 | - Run it by open "Cube/index.html" with Microsoft Edge 34 | -------------------------------------------------------------------------------- /README_zh.md: -------------------------------------------------------------------------------- 1 |

2 | Image 3 |

4 | 5 | # GuiLiteWeb 6 | - [GuiLite](https://gitee.com/idea4good/GuiLite)是最轻量,最简单,最稳定的GUI库,它只有5千行C++代码 7 | - GuiLiteWeb可以把GuiLite注入到网页中 8 | 9 | ## CubeEx 10 | ![GuiLiteCube](doc/GuiLite3D.gif) 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 | ![GuiLiteGraphic](doc/GuiLiteGraphic.gif) 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 | ![GuiLiteCube](doc/GuiLiteCube.gif) 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 --------------------------------------------------------------------------------