Skip to content

Commit 18cfd76

Browse files
committed
Add some PAGPlayer bindings on Web env.
1 parent 6aaefe9 commit 18cfd76

9 files changed

+230
-29
lines changed

Diff for: web/demo/index.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
<button class="mt-24" id="btn-setVideoEnabled">Set videoEnabled</button>
7777
<button class="mt-24" id="btn-cacheEnabled">CacheEnabled status</button>
7878
<button class="mt-24" id="btn-setCacheEnabled">Set cacheEnabled</button>
79-
<!-- <button class="mt-24" id="btn-freeCache">FreeCache</button> -->
79+
<button class="mt-24" id="btn-freeCache">FreeCache</button>
8080
<div class="mt-24">
8181
<button id="btn-cacheScale">CacheScale status</button>
8282
CacheScale

Diff for: web/demo/index.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -228,9 +228,9 @@ window.onload = async () => {
228228
});
229229

230230
// freeCache
231-
// document.getElementById('btn-freeCache').addEventListener('click', () => {
232-
// pagView.freeCache();
233-
// });
231+
document.getElementById('btn-freeCache').addEventListener('click', () => {
232+
pagView.freeCache();
233+
});
234234

235235
// cacheScale
236236
globalCacheScale = 1;

Diff for: web/src/core/scaler-context.ts

+5-11
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
import { NativeImage } from './native-image';
22
import { measureText } from '../utils/measure-text';
33
import { defaultFontNames } from '../utils/font-family';
4-
5-
export interface Bounds {
6-
top: number;
7-
left: number;
8-
bottom: number;
9-
right: number;
10-
}
4+
import { Rect } from '../types';
115

126
const canvas = ((): HTMLCanvasElement | OffscreenCanvas => {
137
try {
@@ -47,7 +41,7 @@ export class ScalerContext {
4741
private readonly fauxBold: boolean;
4842
private readonly fauxItalic: boolean;
4943

50-
private fontBoundingBoxMap: { key: string; value: Bounds }[] = [];
44+
private fontBoundingBoxMap: { key: string; value: Rect }[] = [];
5145

5246
public constructor(fontName: string, size: number, fauxBold = false, fauxItalic = false) {
5347
this.fontName = fontName;
@@ -82,7 +76,7 @@ export class ScalerContext {
8276
context.font = this.fontString();
8377
const metrics = this.measureText(context, text);
8478

85-
const bounds: Bounds = {
79+
const bounds: Rect = {
8680
left: Math.floor(-metrics.actualBoundingBoxLeft),
8781
top: Math.floor(-metrics.actualBoundingBoxAscent),
8882
right: Math.ceil(metrics.actualBoundingBoxRight),
@@ -106,7 +100,7 @@ export class ScalerContext {
106100
};
107101
}
108102

109-
public generateImage(text: string, bounds): NativeImage {
103+
public generateImage(text: string, bounds: Rect): NativeImage {
110104
const canvas = document.createElement('canvas');
111105
canvas.width = bounds.right - bounds.left;
112106
canvas.height = bounds.bottom - bounds.top;
@@ -129,7 +123,7 @@ export class ScalerContext {
129123
const { left, top, right, bottom } = measureText(imageData);
130124
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
131125

132-
let fontMeasure: Bounds;
126+
let fontMeasure: Rect;
133127
const fontBoundingBox = this.fontBoundingBoxMap.find((item) => item.key === this.fontName);
134128
if (fontBoundingBox) {
135129
fontMeasure = fontBoundingBox.value;

Diff for: web/src/core/web-mask.ts

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Matrix } from '../types';
12
import { ScalerContext } from './scaler-context';
23

34
export class WebMask {
@@ -46,7 +47,15 @@ export class WebMask {
4647
}
4748
}
4849

49-
public fillText(size: number, fauxBold: boolean, fauxItalic: boolean, fontName: string, texts, positions, matrix) {
50+
public fillText(
51+
size: number,
52+
fauxBold: boolean,
53+
fauxItalic: boolean,
54+
fontName: string,
55+
texts,
56+
positions,
57+
matrix: Matrix,
58+
) {
5059
const scalerContext = new ScalerContext(fontName, size, fauxBold, fauxItalic);
5160
const context = this.canvas.getContext('2d');
5261
context.transform(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty);
@@ -65,7 +74,7 @@ export class WebMask {
6574
stroke,
6675
texts,
6776
positions,
68-
matrix,
77+
matrix: Matrix,
6978
) {
7079
if (stroke.width < 0.5) {
7180
return;

Diff for: web/src/pag-player.ts

+101-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
import { PAGComposition } from './pag-composition';
12
import { PAGFile } from './pag-file';
3+
import { PAGLayer } from './pag-layer';
24
import { PAGSurface } from './pag-surface';
3-
import { PAG, PAGScaleMode } from './types';
5+
import { Matrix, PAG, PAGScaleMode, Rect, Vector } from './types';
46
import { wasmAwaitRewind, wasmAsyncMethod } from './utils/decorators';
57

68
@wasmAwaitRewind
@@ -121,14 +123,108 @@ export class PAGPlayer {
121123
* Returns the current PAGComposition for PAGPlayer to render as content.
122124
*/
123125
public getComposition(): PAGFile {
124-
const wasmIns = this.wasmIns._getComposition();
125-
return new PAGFile(wasmIns);
126+
return new PAGFile(this.wasmIns._getComposition());
126127
}
127128
/**
128129
* Sets a new PAGComposition for PAGPlayer to render as content.
129130
*/
130-
public setComposition(pagFile: PAGFile) {
131-
this.wasmIns._setComposition(pagFile.wasmIns);
131+
public setComposition(pagComposition: PAGComposition) {
132+
this.wasmIns._setComposition(pagComposition.wasmIns);
133+
}
134+
/**
135+
* Returns the PAGSurface object for PAGPlayer to render onto.
136+
*/
137+
public getSurface(): PAGSurface {
138+
return new PAGSurface(this.wasmIns._getSurface());
139+
}
140+
/**
141+
* Returns a copy of current matrix.
142+
*/
143+
public matrix(): Matrix {
144+
return this.wasmIns._matrix() as Matrix;
145+
}
146+
/**
147+
* Set the transformation which will be applied to the composition. The scaleMode property
148+
* will be set to PAGScaleMode::None when this method is called.
149+
*/
150+
public setMatrix(matrix: Matrix) {
151+
this.wasmIns._setMatrix(matrix);
152+
}
153+
/**
154+
* Set the progress of play position to next frame. It is applied only when the composition is not
155+
* null.
156+
*/
157+
public nextFrame() {
158+
this.wasmIns._nextFrame();
159+
}
160+
/**
161+
* Set the progress of play position to previous frame. It is applied only when the composition is
162+
* not null.
163+
*/
164+
public preFrame() {
165+
this.wasmIns._preFrame();
166+
}
167+
/**
168+
* If true, PAGPlayer clears the whole content of PAGSurface before drawing anything new to it.
169+
* The default value is true.
170+
*/
171+
public autoClear(): boolean {
172+
return this.wasmIns._autoClear() as boolean;
173+
}
174+
/**
175+
* Sets the autoClear property.
176+
*/
177+
public setAutoClear(value: boolean) {
178+
this.wasmIns._setAutoClear(value);
179+
}
180+
/**
181+
* Returns a rectangle that defines the original area of the layer, which is not transformed by
182+
* the matrix.
183+
*/
184+
public getBounds(pagLayer: PAGLayer): Rect {
185+
return this.wasmIns._getBounds(pagLayer.wasmIns) as Rect;
186+
}
187+
/**
188+
* Returns an array of layers that lie under the specified point. The point is in pixels and from
189+
* this PAGComposition's local coordinates.
190+
*/
191+
public getLayersUnderPoint(): Vector<any> {
192+
return this.wasmIns._getLayersUnderPoint();
193+
}
194+
/**
195+
* Evaluates the PAGLayer to see if it overlaps or intersects with the specified point. The point
196+
* is in the coordinate space of the PAGSurface, not the PAGComposition that contains the
197+
* PAGLayer. It always returns false if the PAGLayer or its parent (or parent's parent...) has not
198+
* been added to this PAGPlayer. The pixelHitTest parameter indicates whether or not to check
199+
* against the actual pixels of the object (true) or the bounding box (false). Returns true if the
200+
* PAGLayer overlaps or intersects with the specified point.
201+
*/
202+
public hitTestPoint(pagLayer: PAGLayer, surfaceX: number, surfaceY: number, pixelHitTest = false): boolean {
203+
return this.wasmIns._hitTestPoint(pagLayer.wasmIns, surfaceX, surfaceY, pixelHitTest) as boolean;
204+
}
205+
/**
206+
* The time cost by rendering in microseconds.
207+
*/
208+
public renderingTime(): number {
209+
return this.wasmIns._renderingTime() as number;
210+
}
211+
/**
212+
* The time cost by image decoding in microseconds.
213+
*/
214+
public imageDecodingTime(): number {
215+
return this.wasmIns._imageDecodingTime() as number;
216+
}
217+
/**
218+
* The time cost by presenting in microseconds.
219+
*/
220+
public presentingTime(): number {
221+
return this.wasmIns._presentingTime() as number;
222+
}
223+
/**
224+
* The memory cost by graphics in bytes.
225+
*/
226+
public graphicsMemory(): number {
227+
return this.wasmIns._graphicsMemory() as number;
132228
}
133229

134230
public destroy() {

Diff for: web/src/pag-surface.ts

+28
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,34 @@ export class PAGSurface {
4343
public updateSize(): void {
4444
this.wasmIns._updateSize();
4545
}
46+
/**
47+
* Erases all pixels of this surface with transparent color. Returns true if the content has
48+
* changed.
49+
*/
50+
public clearAll(): boolean {
51+
return this.wasmIns._clearAll() as boolean;
52+
}
53+
/**
54+
* Free the cache created by the surface immediately. Can be called to reduce memory pressure.
55+
*/
56+
public freeCache(): void {
57+
this.wasmIns._freeCache();
58+
}
59+
/**
60+
* Copies pixels from current PAGSurface to dstPixels with specified color type, alpha type and
61+
* row bytes. Returns true if pixels are copied to dstPixels.
62+
*/
63+
// TODO(zenoslin) binding PAGSurface::readPixels
64+
// public readPixels(colorType, alphaType, buffer): boolean {
65+
// const dataUint8Array = new Uint8Array(buffer);
66+
// const numBytes = dataUint8Array.byteLength * dataUint8Array.BYTES_PER_ELEMENT;
67+
// const dataPtr = PAGSurface.module._malloc(numBytes);
68+
// const dataOnHeap = new Uint8Array(PAGSurface.module.HEAPU8.buffer, dataPtr, numBytes);
69+
// dataOnHeap.set(dataUint8Array);
70+
// const res = this.wasmIns._readPixels(colorType, alphaType, dataOnHeap.byteOffset, dataOnHeap.length);
71+
// PAGSurface.module._free(dataPtr);
72+
// return res;
73+
// }
4674

4775
public destroy(): void {
4876
this.wasmIns.delete();

Diff for: web/src/pag-view.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ export class PAGView {
219219
* Free the cache created by the pag view immediately. Can be called to reduce memory pressure.
220220
*/
221221
public freeCache() {
222-
// TODO(akazenoslin): PAGSurface freeCache
222+
this.pagSurface.freeCache();
223223
}
224224
/**
225225
* Returns the current PAGComposition for PAGView to render as content.

Diff for: web/src/pag_wasm_bindings.cpp

+32-6
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include <emscripten/bind.h>
2020
#include <emscripten/val.h>
21+
#include "base/utils/TGFXCast.h"
2122
#include "core/FontMetrics.h"
2223
#include "core/ImageInfo.h"
2324
#include "core/PathTypes.h"
@@ -135,7 +136,9 @@ EMSCRIPTEN_BINDINGS(pag) {
135136
}))
136137
.function("_width", &PAGSurface::width)
137138
.function("_height", &PAGSurface::height)
138-
.function("_updateSize", &PAGSurface::updateSize);
139+
.function("_updateSize", &PAGSurface::updateSize)
140+
.function("_clearAll", &PAGSurface::clearAll)
141+
.function("_freeCache", &PAGSurface::freeCache);
139142

140143
class_<PAGImage>("_PAGImage")
141144
.smart_ptr<std::shared_ptr<PAGImage>>("_PAGImage")
@@ -168,12 +171,35 @@ EMSCRIPTEN_BINDINGS(pag) {
168171
.function("_scaleMode", &PAGPlayer::scaleMode)
169172
.function("_setScaleMode", &PAGPlayer::setScaleMode)
170173
.function("_setSurface", &PAGPlayer::setSurface)
171-
.function("_getComposition", optional_override([](PAGPlayer& pagPlayer) {
172-
return std::static_pointer_cast<PAGFile>(pagPlayer.getComposition());
174+
.function("_getComposition", &PAGPlayer::getComposition)
175+
.function("_setComposition", &PAGPlayer::setComposition)
176+
.function("_getSurface", &PAGPlayer::getSurface)
177+
.function("_matrix",
178+
optional_override([](PAGPlayer& pagPlayer) { return ToTGFX(pagPlayer.matrix()); }))
179+
.function("_setMatrix", optional_override([](PAGPlayer& pagPlayer, tgfx::Matrix matrix) {
180+
pagPlayer.setMatrix(ToPAG(matrix));
173181
}))
174-
.function("_setComposition",
175-
optional_override([](PAGPlayer& pagPlayer, std::shared_ptr<PAGFile>& pagFile) {
176-
pagPlayer.setComposition(std::move(pagFile));
182+
.function("_nextFrame", &PAGPlayer::nextFrame)
183+
.function("_preFrame", &PAGPlayer::preFrame)
184+
.function("_autoClear", &PAGPlayer::autoClear)
185+
.function("_setAutoClear", &PAGPlayer::setAutoClear)
186+
.function("_getBounds",
187+
optional_override([](PAGPlayer& pagPlayer, std::shared_ptr<PAGLayer> pagLayer) {
188+
return ToTGFX(pagPlayer.getBounds(pagLayer));
189+
}))
190+
.function("_getLayersUnderPoint", &PAGPlayer::getLayersUnderPoint)
191+
.function("_hitTestPoint", &PAGPlayer::hitTestPoint)
192+
.function("_renderingTime", optional_override([](PAGPlayer& pagPlayer) {
193+
return static_cast<int>(pagPlayer.renderingTime());
194+
}))
195+
.function("_imageDecodingTime", optional_override([](PAGPlayer& pagPlayer) {
196+
return static_cast<int>(pagPlayer.imageDecodingTime());
197+
}))
198+
.function("_presentingTime", optional_override([](PAGPlayer& pagPlayer) {
199+
return static_cast<int>(pagPlayer.presentingTime());
200+
}))
201+
.function("_graphicsMemory", optional_override([](PAGPlayer& pagPlayer) {
202+
return static_cast<int>(pagPlayer.graphicsMemory());
177203
}));
178204

179205
class_<tgfx::ImageInfo>("ImageInfo")

Diff for: web/src/types.ts

+48
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,54 @@ export interface Color {
182182
blue: number;
183183
}
184184

185+
export declare class Matrix {
186+
/**
187+
* The entry at position [1,1] in the matrix.
188+
*/
189+
public a: number;
190+
/**
191+
* The entry at position [1,2] in the matrix.
192+
*/
193+
public b: number;
194+
/**
195+
* The entry at position [2,1] in the matrix.
196+
*/
197+
public c: number;
198+
/**
199+
* The entry at position [2,2] in the matrix.
200+
*/
201+
public d: number;
202+
/**
203+
* The entry at position [3,1] in the matrix.
204+
*/
205+
public tx: number;
206+
/**
207+
* The entry at position [3,2] in the matrix.
208+
*/
209+
public ty: number;
210+
private constructor();
211+
}
212+
213+
export declare class Rect {
214+
/**
215+
* smaller x-axis bounds.
216+
*/
217+
public left: number;
218+
/**
219+
* smaller y-axis bounds.
220+
*/
221+
public top: number;
222+
/**
223+
* larger x-axis bounds.
224+
*/
225+
public right: number;
226+
/**
227+
* larger y-axis bounds.
228+
*/
229+
public bottom: number;
230+
private constructor();
231+
}
232+
185233
export declare class TextDocument {
186234
/**
187235
* When true, the text layer shows a fill.

0 commit comments

Comments
 (0)