<img src="https://pag.art/img/readme/logo.png" alt="PAG Logo" width="474"/>

[Homepage](https://pag.art) | English | [简体中文](./README.zh_CN.md)

## Introduction

libpag is a real-time rendering library for PAG (Portable Animated Graphics) files that renders both
vector-based and raster-based animations across most platforms, such as iOS, Android, macOS,
Windows, Linux, and Web.

## Features

PAG Web SDK is built on WebAssembly and WebGL which supports all of the PAG features.

## Quick start

PAG Web SDK consists of two files: `libpag.js` and `libpag.wasm`.

### Browser (Recommend)

Use <script/> to include the library directly, `libpag` will be registered as a global variable.

For production use, we recommend using a specific version number of libpag to avoid unexpected breakage from newer versions:

```html
<script src="https://cdn.jsdelivr.net/npm/libpag@4.1.8/lib/libpag.min.js"></script>
```

You can browse the files of the NPM package at the public CDN [cdn.jsdelivr.net/npm/libpag/](https://cdn.jsdelivr.net/npm/libpag/) , and you can use the keyword `@lastest` to get the lastest version.

The PAG library is also available on other public CDNs that sync with NPM, such as [unpkg](https://unpkg.com/libpag@latest/lib/libpag.min.js).

```html
<canvas class="canvas" id="pag"></canvas>
<script src="https://cdn.jsdelivr.net/npm/libpag@latest/lib/libpag.min.js"></script>
<script>
  window.onload = async () => {
    // Initialize pag webassembly module.
    const PAG = await window.libpag.PAGInit();
    // Fetch pag file data.
    const buffer = await fetch('https://pag.art/file/like.pag').then((response) => response.arrayBuffer());
    // Load the PAGFile from data.
    const pagFile = await PAG.PAGFile.load(buffer);
    // Set canvas size from the PAGFile size.
    const canvas = document.getElementById('pag');
    canvas.width = pagFile.width();
    canvas.height = pagFile.height();
    // Create PAGView.
    const pagView = await PAG.PAGView.init(pagFile, canvas);
    // Play PAGView.
    await pagView.play();
  };
</script>
```

You can use the `locateFile` function to get the path of `libpag.wasm` file. By default, the `libpag.wasm` file is located next to the `libpag.js` file. For example:

```js
const PAG = await window.libpag.PAGInit({
  locateFile: () => {
    if (location.host === 'dev.pag.art') {
      // development environment
      return 'https://dev.pag.art/file/libpag.wasm';
    } else {
      // production environment
      return 'https://pag.art/file/libpag.wasm';
    }
  },
});
```

### EsModule

```bash
$ npm i libpag
```

```js
import { PAGInit } from 'libpag';

PAGInit().then((PAG) => {
  // Initialize pag webassembly module.
});
```

**Note: If you are using ESModule to import PAG Web SDK, you must pack the `libpag.wasm` file manually into the final web program, because the common packing tools usually ignore the wasm file. Then use the `locateFile` function to get the path of the `libpag.wasm` . You also need to upload the `libpag.wasm` file to a server so that users can load it from network.**

There are many kinds of products in the npm package after building. You could read the [doc](./doc/develop-install.md) to know about them.

There is also a [repository](https://github.com/libpag/pag-web) that contains some demos about using PAG Web SDK with HTML / Vue / React / PixiJS.

You can find the API documentation [here](https://pag.art/docs/apis-web.html).

## Browser

| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br/>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br/>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br/>Chrome for Android | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br/>Safari on iOS | QQ Browser Mobile |
| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ----------------- |
| Chrome >= 69                                                 | Safari >= 11.3                                               | Android >= 7.0                                               | iOS >= 11.3                                                  | last 2 versions   |

More compatible versions are coming soon.

## Roadmap

Please visit [here](https://github.com/Tencent/libpag/wiki/PAG-Web-roadmap) to see the roadmap of the PAG Web SDK.

## Development

First, make sure you have installed all the tools and dependencies listed in the [README.md](../README.md#Development) located in the project root directory.

### Dependency Management

Then run the following command to install required node modules:

```bash
$ npm install
```

### Build (Debug)

Execute `build.sh debug` to get `libpag.wasm` file.

```bash
# ./web/script/
$ cd script
$ chmod +x ./build.sh
$ ./build.sh debug
```

Build Typescript file.

```bash
# ./web/
$ npm run dev
```

Start HTTP server.

```bash
# ./
$ npm run server
```
Use Chrome to open `http://localhost:8081/web/demo/index.html` to see the demo.

If you need to debug, you can install [C/C++ DevTools Support (DWARF)](https://chrome.google.com/webstore/detail/cc%20%20-devtools-support-dwa/pdcpmagijalfljmkmjngeonclgbbannb), and open Chrome DevTools > Settings > Experiments > Check the "WebAssembly Debugging: Enable DWARF support" option to enable SourceMap support. Now you can debug C++ files in Chrome DevTools.

#### PS

When using build.sh to compile libpag.wasm, undefined symbols error was suppressed due to compatibility issues between emscripten and the system's std library.

```shell
# build.sh
emcc -s ERROR_ON_UNDEFINED_SYMBOLS=0
```

During the compilation process, it is necessary to pay attention to any warning messages unrelated to std library to avoid the undefined symbols errors during runtime.

### Build (Release)

```bash
# ./web/script
$ cd script
$ chmod +x ./build.sh
$ ./build.sh
```

### Build with CLion

Create a new build target in CLion, and use the following **CMake options**（find them under **CLion** > **Preferences** > **Build, Execution, Deployment** > **CMake**）

```
-DCMAKE_TOOLCHAIN_FILE=path/to/emscripten/emscripten/version/cmake/Modules/Platform/Emscripten.cmake
```

### Test

Build release version

```bash
$ cd script & ./build.sh
```

Start test HTTP server.

```bash
$ npm run server
```

Start cypress test.

```bash
$ npm run test
```
