From 82a95693e6c2a9bc2d74338ed6ff447998651bd9 Mon Sep 17 00:00:00 2001 From: renzhilan <903198975@qq.com> Date: Tue, 15 Feb 2022 23:33:33 +0800 Subject: [PATCH] Add pag-Composition class bindings method in web (#111) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add pagposition class binding method and audio play dome * fix: Remove asynchronous function * fix:Remove asynchronous function * Fix audioPlayer class * Remove Log.log() function * Fix adjust annotation Co-authored-by: 任志强 --- web/demo/index.css | 97 ++++++++++++++++++++++ web/demo/index.html | 152 ++++++++++++++++++++-------------- web/demo/index.ts | 135 +++++++++++++++++++++++++++++- web/demo/js/audio-player.ts | 43 ++++++++++ web/src/pag-composition.ts | 100 +++++++++++++++++++++- web/src/pag_wasm_bindings.cpp | 44 +++++++++- web/src/types.ts | 9 ++ web/src/utils/log.ts | 4 +- 8 files changed, 514 insertions(+), 70 deletions(-) create mode 100644 web/demo/js/audio-player.ts diff --git a/web/demo/index.css b/web/demo/index.css index 470b81e6b8..07b80f046a 100644 --- a/web/demo/index.css +++ b/web/demo/index.css @@ -37,3 +37,100 @@ button { input { font-size: 16px; } + +.ac-container { + margin: 10px auto 30px auto; +} + +.ac-container label { + font-family: 'BebasNeueRegular', 'Arial Narrow', Arial, sans-serif; + padding: 5px 20px; + position: relative; + display: block; + height: 30px; + cursor: pointer; + color: #777; + text-shadow: 1px 1px 1px rgba(255,255,255,0.8); + line-height: 33px; + font-size: 19px; + background: #ffffff; + background: -moz-linear-gradient(top, #ffffff 1%, #eaeaea 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(1%,#ffffff), color-stop(100%,#eaeaea)); + background: -webkit-linear-gradient(top, #ffffff 1%,#eaeaea 100%); + background: -o-linear-gradient(top, #ffffff 1%,#eaeaea 100%); + background: -ms-linear-gradient(top, #ffffff 1%,#eaeaea 100%); + background: linear-gradient(top, #ffffff 1%,#eaeaea 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#eaeaea',GradientType=0 ); + box-shadow: + 0px 0px 0px 1px rgba(155,155,155,0.3), + 1px 0px 0px 0px rgba(255,255,255,0.9) inset, + 0px 2px 2px rgba(0,0,0,0.1); +} + +.ac-container label:hover { + background: #fff; +} + +.ac-container input:checked + label, +.ac-container input:checked + label:hover { + background: #0252d9; + color: white; + text-shadow: 0px 1px 1px rgba(255,255,255, 0.6); + box-shadow: + 0px 0px 0px 1px rgba(155,155,155,0.3), + 0px 2px 2px rgba(0,0,0,0.1); +} + +.ac-container label:hover:after, +.ac-container input:checked + label:hover:after { + content: ''; + position: absolute; + width: 24px; + height: 24px; + right: 13px; + top: 7px; + background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAJCAYAAAACTR1pAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjJDQjg3QjIzNUEwQTExRTFCMzhGODE4MEUyMzVCOUExIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjJDQjg3QjI0NUEwQTExRTFCMzhGODE4MEUyMzVCOUExIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MkNCODdCMjE1QTBBMTFFMUIzOEY4MTgwRTIzNUI5QTEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MkNCODdCMjI1QTBBMTFFMUIzOEY4MTgwRTIzNUI5QTEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5cTChyAAAAsUlEQVR42mJcduA0AxBkAvEOIL7PgBuwAXE1EHcA8XcmIFEBxNOA+DAQq+DRtBqI64B4CxBzgjS6QiWlgfgAEKtj0bQOiP2gfF0gVgRp9AHifUia9yJpBmnaCMTeUP5rIHYG4msgjd+xaAbZbADV5IGkyQGIL4M4TFBBmObdUL4EEJ9H0vQCqukazP1MSH4BafZH0syApMkZWRO6RmTNO/BpwqYRpjkIiBegOw8ZAAQYAErPJ/hwLstPAAAAAElFTkSuQmCC) no-repeat center center; +} + +.ac-container input:checked + label:hover:after { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAJCAYAAAACTR1pAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjIxMjY0NjgzNUEwQTExRTFBMkMwQUUyOEY2NjkzRDMyIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjIxMjY0Njg0NUEwQTExRTFBMkMwQUUyOEY2NjkzRDMyIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MjEyNjQ2ODE1QTBBMTFFMUEyQzBBRTI4RjY2OTNEMzIiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MjEyNjQ2ODI1QTBBMTFFMUEyQzBBRTI4RjY2OTNEMzIiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4kGTYVAAAAlklEQVR42mJcduA0AxbACcTTgLgDiG9iU8CEQ9M6IE4A4gNArEWMRpCmjUDsAeVLAPFebJqZsGhyRVODVTMTkqYtSJpeALEhEO9A0ozibCYkTU5QsadA7ADEF4DYH0mzKFSzLkwjuiZnpJD8hUUz2NkgjbtxaGJA07wVyr8GxPdZoHH1BWrqHQbsAKQ5CIiroeq/AwQYALFQJdCqpXTVAAAAAElFTkSuQmCC); +} + +.ac-container .ac-check { + display: none; +} + +.ac-container article { + background: rgba(255, 255, 255, 0.5); + margin-top: -1px; + overflow: hidden; + height: 0px; + position: relative; + z-index: 10; + -webkit-transition: height 0.3s ease-in-out, box-shadow 0.6s linear; + -moz-transition: height 0.3s ease-in-out, box-shadow 0.6s linear; + -o-transition: height 0.3s ease-in-out, box-shadow 0.6s linear; + -ms-transition: height 0.3s ease-in-out, box-shadow 0.6s linear; + transition: height 0.3s ease-in-out, box-shadow 0.6s linear; +} + +.ac-container input:checked ~ article { + -webkit-transition: height 0.5s ease-in-out, box-shadow 0.1s linear; + -moz-transition: height 0.5s ease-in-out, box-shadow 0.1s linear; + -o-transition: height 0.5s ease-in-out, box-shadow 0.1s linear; + -ms-transition: height 0.5s ease-in-out, box-shadow 0.1s linear; + transition: height 0.5s ease-in-out, box-shadow 0.1s linear; + box-shadow: 0px 0px 0px 1px rgba(155,155,155,0.3); +} +.support-method .title{ + font-size: 18px; + color: black; + font-weight: 600; + margin-bottom: 10px; +} + +.ac-container input:checked ~ article.ac-large { + height: auto; + padding: 25px; + padding-top: 8px; +} \ No newline at end of file diff --git a/web/demo/index.html b/web/demo/index.html index 4d79c78ba4..4053cd1033 100644 --- a/web/demo/index.html +++ b/web/demo/index.html @@ -13,6 +13,7 @@
+
@@ -29,69 +30,94 @@
diff --git a/web/demo/index.ts b/web/demo/index.ts index 48aa9a5f34..55f8defca0 100644 --- a/web/demo/index.ts +++ b/web/demo/index.ts @@ -1,6 +1,7 @@ import { PAGInit } from '../src/pag'; import { PAGFile } from '../src/pag-file'; import { PAGView } from '../src/pag-view'; +import { AudioPlayer } from './js/audio-player'; import { PAG as PAGNamespace, PAGViewListenerEvent } from '../src/types'; declare global { @@ -15,6 +16,8 @@ let cacheEnabled: boolean; let videoEnabled: boolean; let globalCacheScale: number; let videoEl = null; +let pagComposition = null; +let audioEl = null; let PAG: PAGNamespace; let canvasElementSize = 640; let isMobile = false; @@ -148,18 +151,22 @@ window.onload = async () => { // 控制 document.getElementById('btn-play').addEventListener('click', () => { pagView.play(); + audioEl.play(); console.log('开始'); }); document.getElementById('btn-pause').addEventListener('click', () => { pagView.pause(); + audioEl.pause(); console.log('暂停'); }); document.getElementById('btn-stop').addEventListener('click', () => { pagView.stop(); + audioEl.stop(); console.log('停止'); }); - document.getElementById('btn-destroy').addEventListener('click', function () { + document.getElementById('btn-destroy').addEventListener('click', () => { pagView.destroy(); + audioEl.destroy(); console.log('销毁'); }); @@ -223,6 +230,11 @@ window.onload = async () => { pagView.setCacheEnabled(!cacheEnabled); }); + // PAGComposition + document.getElementById('btn-composition').addEventListener('click', () => { + testPAGCompositionAPi(); + }); + // freeCache // document.getElementById('btn-freeCache').addEventListener('click', () => { // pagView.freeCache(); @@ -243,6 +255,119 @@ window.onload = async () => { }); }; +const existsLayer = (pagLayerWasm: object) => { + if (pagLayerWasm) return true; + console.log('no Layer'); + return false; +} + +// PAGComposition api test +const testPAGComposition = { + rect: () => { + console.log(`test result: width: ${pagComposition.width()}, height: ${pagComposition.height()}`) + }, + setContentSize: () => { + pagComposition.setContentSize(360, 640); + console.log(`test setContentSize result: width: ${pagComposition.width()}, height: ${pagComposition.height()}`) + }, + numChildren: () => { + console.log(`test numChildren: ${pagComposition.numChildren()}`) + }, + getLayerAt: () => { + const pagLayerWasm = pagComposition.getLayerAt(0); + if (!existsLayer(pagLayerWasm)) return; + const pagLayer = new PAG.PAGLayer(pagLayerWasm); + console.log(`test getLayerAt index 0, layerName: ${pagLayer.layerName()}`) + }, + getLayersByName: () => { + const pagLayerWasm = pagComposition.getLayerAt(0); + if(!existsLayer(pagLayerWasm)) return; + const pagLayer = new PAG.PAGLayer(pagLayerWasm); + const layerName = pagLayer.layerName(); + const vectorPagLayer = pagComposition.getLayersByName(layerName); + for (let j = 0; j < vectorPagLayer.size(); j++) { + const pagLayerWasm = vectorPagLayer.get(j); + const pagLayer_1 = new PAG.PAGLayer(pagLayerWasm); + console.log(`test getLayersByName: layerName: ${pagLayer_1.layerName()}`); + } + }, + audioStartTime: () => { + const audioStartTime = pagComposition.audioStartTime(); + console.log('test audioStartTime:', audioStartTime); + }, + audioMarkers: () => { + const audioMarkers = pagComposition.audioMarkers(); + console.log(`test audioMarkers: size`, audioMarkers.size()); + }, + audioBytes: () => { + const audioBytes = pagComposition.audioBytes(); + console.log('test audioBytes:', audioBytes); + }, + getLayerIndex: () => { + const pagLayerWasm = pagComposition.getLayerAt(0); + const index = pagComposition.getLayerIndex(pagLayerWasm); + console.log(`test GetLayerIndex: ${index}`); + }, + swapLayerAt: () => { + swapLayer('swapLayerAt'); + }, + swapLayer: () => { + swapLayer('swapLayer'); + }, + contains: () => { + const pagLayerWasm = pagComposition.getLayerAt(0); + const isContains = pagComposition.contains(pagLayerWasm); + if (isContains) { console.log('test contains'); } + }, + addLayer: () => { + const pagLayerWasm = pagComposition.getLayerAt(0); + pagComposition.removeLayerAt(0); + const oldNum = pagComposition.numChildren(); + const isSuccess: boolean = pagComposition.addLayer(pagLayerWasm); + if (isSuccess) { console.log(`test addLayer success: old num ${oldNum} current num ${pagComposition.numChildren()}`)}; + }, + removeLayerAt: () => { + const oldNum = pagComposition.numChildren(); + pagComposition.removeLayerAt(0); + console.log(`test delete Layer[0] success: old LayersNum: ${oldNum} current LayersNum ${pagComposition.numChildren()}`); + }, + removeAllLayers: () => { + const oldNum = pagComposition.numChildren(); + pagComposition.removeAllLayers(); + console.log(`test removeAllLayers success: old LayersNum${oldNum} current LayersNum ${pagComposition.numChildren()}`); + } +} +const testPAGCompositionAPi = () => { + console.log(`-------------------TEST PAGCompositionAPI START--------------------- `); + for (let i in testPAGComposition) { + if (testPAGComposition.hasOwnProperty(i)) { + testPAGComposition[i](); + } + } + console.log(`-------------------TEST PAGCompositionAPI END--------------------- `); +} + +const swapLayer = (type: string) => { + const pagLayerWasm_0 = pagComposition.getLayerAt(0); + const pagLayerWasm_1 = pagComposition.getLayerAt(1); + if (!pagLayerWasm_0 || !pagLayerWasm_1) { + console.log('No layer switching'); + return; + }; + const pagLayer_name_0 = new PAG.PAGLayer(pagLayerWasm_0).layerName(); + const pagLayer_name_1 = new PAG.PAGLayer(pagLayerWasm_1).layerName(); + if (type === 'swapLayer') { + pagComposition.swapLayer(pagLayerWasm_0, pagLayerWasm_1); + } else { + pagComposition.swapLayerAt(0, 1); + } + const pagLayerWasm_exch_0 = pagComposition.getLayerAt(0); + const pagLayerWasm_exch_1 = pagComposition.getLayerAt(1); + const pagLayer__exch_0 = (new PAG.PAGLayer(pagLayerWasm_exch_0).layerName()); + const pagLayer__exch_1 = (new PAG.PAGLayer(pagLayerWasm_exch_1).layerName()); + console.log(`test ${type}: oldLayerName_0=${pagLayer_name_0}, oldLayerName_1=${pagLayer_name_1} exchange LayerName_0=${pagLayer__exch_0}, LayerName_1=${pagLayer__exch_1} `); +} + const createPAGView = async (file) => { if (pagFile) pagFile.destroy(); if (pagView) pagView.destroy(); @@ -264,13 +389,17 @@ const createPAGView = async (file) => { }); pagView.addListener(PAGViewListenerEvent.onAnimationRepeat, (event) => { console.log('onAnimationRepeat', event); + audioEl.stop(); + audioEl.play(); }); document.getElementById('control').style.display = ''; // 图层编辑 const editableLayers = getEditableLayer(PAG, pagFile); console.log(editableLayers); renderEditableLayer(editableLayers); - console.log(`已加载 ${file.name}`); + console.log(`已加载 ${file.name}`); + pagComposition = pagView.getComposition(); + audioEl = new AudioPlayer(pagComposition.audioBytes()); return pagView; }; @@ -346,7 +475,7 @@ const renderEditableLayer = (editableLayers) => { item.appendChild(replaceVideoBtn); box.appendChild(item); }); - document.body.appendChild(box); + document.querySelector('#editLayer-content').appendChild(box) }; // 替换图片 diff --git a/web/demo/js/audio-player.ts b/web/demo/js/audio-player.ts new file mode 100644 index 0000000000..9b0bf4af75 --- /dev/null +++ b/web/demo/js/audio-player.ts @@ -0,0 +1,43 @@ +export class AudioPlayer { + private audioEl: HTMLAudioElement = null; + private isEffective = true; + private isDestroyed = false; + + public constructor(audioBytes: Uint8Array) { + if (audioBytes.byteLength > 0){ + this.audioEl = document.createElement('audio'); + this.audioEl.style.display = 'none'; + this.audioEl.controls = true; + this.audioEl.preload = 'preload'; + const blob = new Blob([audioBytes], { type: 'audio/mp3' }); + this.audioEl.src = URL.createObjectURL(blob); + this.isDestroyed = false + } else { + this.isEffective = false; + } + console.log(`${audioBytes.byteLength === 0 ? '无音频文件' : '有音频文件'}`) + } + public play() { + if (!this.isEffective || this.isDestroyed) return; + this.audioEl.play(); + console.log('音频播放'); + } + public pause() { + if (!this.isEffective || this.isDestroyed) return; + this.audioEl.pause(); + console.log('音频暂停'); + } + public stop() { + if (!this.isEffective || this.isDestroyed) return; + this.audioEl.currentTime = 0; + this.audioEl.pause(); + console.log('音频停止'); + } + public destroy() { + if (!this.isEffective || this.isDestroyed) return; + console.log('音频销毁'); + this.audioEl.pause(); + this.audioEl = null; + this.isDestroyed = true + } +} diff --git a/web/src/pag-composition.ts b/web/src/pag-composition.ts index 5ddc2be91b..654c76ecf6 100644 --- a/web/src/pag-composition.ts +++ b/web/src/pag-composition.ts @@ -1,4 +1,4 @@ -import { PAG } from './types'; +import { PAG, Marker } from './types'; import { PAGLayer } from './pag-layer'; import { wasmAwaitRewind } from './utils/decorators'; @@ -21,4 +21,102 @@ export class PAGComposition extends PAGLayer { public height(): number { return this.wasmIns._height() as number; } + /** + * Returns the number of child layers of this composition. + */ + public numChildren(): number { + return this.wasmIns._numChildren() as number; + } + /** + * Set the width and height of the Composition. + */ + public setContentSize(width: number, height: number): void { + this.wasmIns._setContentSize(width, height); + } + /** + * Returns the child layer that exists at the specified index. + * @param index The index position of the child layer. + * @returns The child layer at the specified index position. + */ + public getLayerAt(index: number): PAGLayer { + return this.wasmIns._getLayerAt(index) as PAGLayer; + } + /** + * Returns an array of layers that match the specified layer name. + */ + public getLayersByName(layerName: string): Array { + return this.wasmIns._getLayersByName(layerName) as Array; + } + /** + * Returns the index position of a child layer. + * @param pagLayer The layer instance to identify. + * @returns The index position of the child layer to identify. + */ + public getLayerIndex(index: number): PAGLayer { + return this.wasmIns._getLayerIndex(index) as PAGLayer; + } + /** + * Swap the layers at the specified index. + */ + public swapLayer(pagLayer1: PAGLayer, pagLayer2: PAGLayer): void { + this.wasmIns._swapLayer(pagLayer1, pagLayer2); + } + /** + * Swap the layers at the specified index. + */ + public swapLayerAt(index1: number, index2: number): void { + this.wasmIns._swapLayerAt(index1, index2); + } + /** + * Check whether current PAGComposition contains the specified pagLayer. + */ + public contains(pagLayer: PAGLayer): boolean { + return this.wasmIns._contains(pagLayer); + } + /** + * Add a PAGLayer to current PAGComposition at the top. If you add a layer that already has a + * different PAGComposition object as a parent, the layer is removed from the other PAGComposition + * object. + */ + public addLayer(layer: PAGLayer): boolean { + return this.wasmIns._addLayer(layer) as boolean; + } + /** + * Add a PAGLayer to current PAGComposition at the top. If you add a layer that already has a + * different PAGComposition object as a parent, the layer is removed from the other PAGComposition + * object. + */ + public addLayerAt(layer: PAGLayer, index: number): boolean { + return this.wasmIns._addLayerAt(layer, index) as boolean; + } + /** + * Indicates when the first frame of the audio plays in the composition's timeline. + */ + public audioStartTime(): number { + return this.wasmIns._audioStartTime() as number; + } + /** + * Returns the audio markers of this composition. + */ + public audioMarkers(): Array { + return this.wasmIns._audioMarkers() as Array; + } + /** + * The audio data of this composition. + */ + public audioBytes(): Uint8Array { + return this.wasmIns._audioBytes() as Uint8Array; + } + /** + * Remove the specified PAGLayer from current PAGComposition. + */ + public removeLayerAt(index: number): PAGLayer { + return this.wasmIns._removeLayerAt(index) as PAGLayer; + } + /** + * Remove all PAGLayers from current PAGComposition. + */ + public removeAllLayers(): void { + this.wasmIns._removeAllLayers(); + } } diff --git a/web/src/pag_wasm_bindings.cpp b/web/src/pag_wasm_bindings.cpp index 1690365869..4ce66ac23b 100644 --- a/web/src/pag_wasm_bindings.cpp +++ b/web/src/pag_wasm_bindings.cpp @@ -17,6 +17,7 @@ ///////////////////////////////////////////////////////////////////////////////////////////////// #include +#include #include "core/FontMetrics.h" #include "core/ImageInfo.h" #include "core/PathTypes.h" @@ -61,7 +62,42 @@ EMSCRIPTEN_BINDINGS(pag) { class_>("_PAGComposition") .smart_ptr>("_PAGComposition") .function("_width", &PAGComposition::width) - .function("_height", &PAGComposition::height); + .function("_height", &PAGComposition::height) + .function("_setContentSize", &PAGComposition::setContentSize) + .function("_numChildren", &PAGComposition::numChildren) + .function("_getLayerAt", &PAGComposition::getLayerAt) + .function("_getLayerIndex", &PAGComposition::getLayerIndex) + .function("_swapLayerAt", &PAGComposition::swapLayerAt) + .function("_swapLayer", &PAGComposition::swapLayer) + .function("_contains", optional_override([](PAGComposition& pagComposition, + std::shared_ptr pagLayer) { + return static_cast(pagComposition.contains(pagLayer)); + })) + .function("_removeLayerAt", &PAGComposition::removeLayerAt) + .function("_removeAllLayers", &PAGComposition::removeAllLayers) + .function("_addLayer", optional_override([](PAGComposition& pagComposition, + std::shared_ptr pagLayer) { + return static_cast(pagComposition.addLayer(pagLayer)); + })) + .function("_addLayerAt", optional_override([](PAGComposition& pagComposition, + std::shared_ptr pagLayer, int index) { + return static_cast(pagComposition.addLayerAt(pagLayer, index)); + })) + .function("_audioBytes", optional_override([](PAGComposition& pagComposition) { + ByteData* result = pagComposition.audioBytes(); + if (result->length() == 0) { + uint8_t empty_arr[] = {}; + return val(typed_memory_view(0, empty_arr)); + } + return val(typed_memory_view(result->length(), result->data())); + })) + .function("_audioMarkers", &PAGComposition::audioMarkers) + .function("_audioStartTime", optional_override([](PAGComposition& pagComposition) { + return static_cast(pagComposition.audioStartTime()); + })) + .function("_getLayersByName", &PAGComposition::getLayersByName) + .function("_getLayersUnderPoint", &PAGComposition::getLayersUnderPoint); + class_>("_PAGFile") .smart_ptr>("_PAGFile") .class_function("_Load", optional_override([](uintptr_t bytes, size_t length) { @@ -215,6 +251,11 @@ EMSCRIPTEN_BINDINGS(pag) { .field("green", &Color::green) .field("blue", &Color::blue); + value_object("Marker") + .field("startTime", &Marker::startTime) + .field("duration", &Marker::duration) + .field("comment", &Marker::comment); + enum_("PathFillType") .value("WINDING", PathFillType::Winding) .value("EVEN_ODD", PathFillType::EvenOdd) @@ -249,6 +290,7 @@ EMSCRIPTEN_BINDINGS(pag) { register_vector>("VectorPAGLayer"); register_vector("VectorString"); register_vector("VectorPoint"); + register_vector("VectorMarker"); function("_SetFallbackFontNames", optional_override([](std::vector fontNames) { PAGFont::SetFallbackFontNames(fontNames); diff --git a/web/src/types.ts b/web/src/types.ts index 67e5a86156..61b2b6c70e 100644 --- a/web/src/types.ts +++ b/web/src/types.ts @@ -117,6 +117,15 @@ export interface Point { y: number; } +/** + * Marker stores comments and other metadata and mark important times in a composition or layer. + */ + export interface Marker { + startTime: number; + duration : number; + comment: string; +}; + export declare class TextDocument { /** * When true, the text layer shows a fill. diff --git a/web/src/utils/log.ts b/web/src/utils/log.ts index ee72837d71..d03eb95140 100644 --- a/web/src/utils/log.ts +++ b/web/src/utils/log.ts @@ -1,8 +1,8 @@ import { ErrorCode, ErrorMap } from './error-map'; export class Log { - public static log(message) { - console.log(message); + public static log(...args) { + console.log(...args); } public static error(error: string) {