Skip to content

Commit

Permalink
Implement lazy font loading (off by default)
Browse files Browse the repository at this point in the history
Extracts default.woff2 from binary, embeds fonts.conf,
removes .data files on output.
Use --memory-init-file=0 to remove .mem files on output.
Specify fallbackFont to override default.woff2.
If lazyFileLoading is set to true, use FS.createLazyFile(). This is
off by default, as it depends on correct HTTP headers sent back.

Cherry-picked from: libass@7988397
  • Loading branch information
WeebDataHoarder authored and dmitrylyzo committed Jun 7, 2023
1 parent 3df655a commit 06edd4f
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 14 deletions.
11 changes: 7 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -155,16 +155,16 @@ all-src:
EMCC_COMMON_ARGS = \
$(LDFLAGS) \
-s EXPORTED_FUNCTIONS="['_main', '_malloc']" \
-s DEFAULT_LIBRARY_FUNCS_TO_INCLUDE="['\$$Browser']" \
-s EXPORTED_RUNTIME_METHODS="['ccall', 'cwrap', 'getValue', 'FS_createPreloadedFile', 'FS_createPath']" \
--use-preload-plugins \
--preload-file assets/default.woff2 \
--preload-file assets/fonts.conf \
--embed-file assets/fonts.conf \
-s ALLOW_MEMORY_GROWTH=1 \
-s NO_FILESYSTEM=0 \
--memory-init-file=0 \
--no-heap-copy \
-o $@

dist: src/subtitles-octopus-worker.bc dist/js/subtitles-octopus-worker.js dist/js/subtitles-octopus-worker-legacy.js dist/js/subtitles-octopus.js dist/js/COPYRIGHT
dist: src/subtitles-octopus-worker.bc dist/js/subtitles-octopus-worker.js dist/js/subtitles-octopus-worker-legacy.js dist/js/subtitles-octopus.js dist/js/COPYRIGHT dist/js/default.woff2

dist/js/subtitles-octopus-worker.js: src/subtitles-octopus-worker.bc src/pre-worker.js src/SubOctpInterface.js src/post-worker.js build/lib/brotli/js/decode.js
mkdir -p dist/js
Expand Down Expand Up @@ -202,6 +202,9 @@ dist/license/all:
dist/js/COPYRIGHT: dist/license/all
cp "$<" "$@"

dist/js/default.woff2:
cp assets/default.woff2 "$@"

# Clean Tasks

clean: clean-dist clean-libs clean-octopus
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ When creating an instance of SubtitleOctopus, you can set the following options:
- `fonts`: An array of links to the fonts used in the subtitle. (Optional)
- `availableFonts`: Object with all available fonts - Key is font name in lower
case, value is link: `{"arial": "/font1.ttf"}` (Optional)
- `fallbackFont`: URL to override fallback font, for example, with a CJK one. Default fallback font is Liberation Sans (Optional)
- `lazyFileLoading`: A boolean, whether to load files in a lazy way via [FS.createLazyFile()](https://emscripten.org/docs/api_reference/Filesystem-API.html#FS.createLazyFile). [Requires](https://github.com/emscripten-core/emscripten/blob/c7b21c32fef92799da05d15ba1939b6394fe0373/src/library_fs.js#L1679-L1856) `Access-Control-Expose-Headers` for `Accept-Ranges, Content-Length, and Content-Encoding`. If encoding is compressed or length is not set, file will be fully fetched instead of just a HEAD request.
- `timeOffset`: The amount of time the subtitles should be offset from the
video. (Default: `0`)
- `onReady`: Function that's called when SubtitlesOctopus is ready. (Optional)
Expand Down
13 changes: 10 additions & 3 deletions src/SubtitleOctopus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <string>
#include <ass/ass.h>

#include "libass.cpp"
Expand Down Expand Up @@ -294,6 +295,8 @@ class SubtitleOctopus {

int status;

std::string defaultFont;

SubtitleOctopus(): ass_library(NULL), ass_renderer(NULL), track(NULL), canvas_w(0), canvas_h(0), status(0), m_is_event_animated(NULL), m_drop_animations(false) {
}

Expand All @@ -311,7 +314,11 @@ class SubtitleOctopus {
return m_drop_animations;
}

void initLibrary(int frame_w, int frame_h) {
void initLibrary(int frame_w, int frame_h, char* default_font) {
if (default_font != NULL) {
defaultFont.assign(default_font);
}

ass_library = ass_library_init();
if (!ass_library) {
fprintf(stderr, "jso: ass_library_init failed!\n");
Expand Down Expand Up @@ -390,11 +397,11 @@ class SubtitleOctopus {
void reloadLibrary() {
quitLibrary();

initLibrary(canvas_w, canvas_h);
initLibrary(canvas_w, canvas_h, NULL);
}

void reloadFonts() {
ass_set_fonts(ass_renderer, "/assets/default.woff2", NULL, ASS_FONTPROVIDER_FONTCONFIG, "/assets/fonts.conf", 1);
ass_set_fonts(ass_renderer, defaultFont.c_str(), NULL, ASS_FONTPROVIDER_FONTCONFIG, "/assets/fonts.conf", 1);
}

void setMargin(int top, int bottom, int left, int right) {
Expand Down
2 changes: 1 addition & 1 deletion src/SubtitleOctopus.idl
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ interface SubtitleOctopus {
void setLogLevel(long level);
void setDropAnimations(long value);
long getDropAnimations();
void initLibrary(long frame_w, long frame_h);
void initLibrary(long frame_w, long frame_h, DOMString default_font);
void createTrack(DOMString subfile);
void createTrackMem(DOMString buf, unsigned long bufsize);
void removeTrack();
Expand Down
15 changes: 11 additions & 4 deletions src/post-worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,18 @@ self.writeFontToFS = function(font) {
self.fontMap_[font] = true;

if (!self.availableFonts.hasOwnProperty(font)) return;
var content = readBinary(self.availableFonts[font]);

Module["FS"].writeFile('/fonts/font' + (self.fontId++) + '-' + self.availableFonts[font].split('/').pop(), content, {
encoding: 'binary'
});
self.loadFontFile('font' + (self.fontId++) + '-', self.availableFonts[font]);
};

self.loadFontFile = function (fontId, path) {
if (self.lazyFileLoading && path.indexOf("blob:") !== 0) {
Module["FS"].createLazyFile("/fonts", fontId + path.split('/').pop(), path, true, false);
} else {
Module["FS"].createPreloadedFile("/fonts", fontId + path.split('/').pop(), path, true, false);
}
}

/**
* Write all font's mentioned in the .ass file to the virtual FS.
* @param {!string} content the file content.
Expand Down Expand Up @@ -611,6 +616,8 @@ function onMessageFromMainEmscriptenThread(message) {
}

self.availableFonts = message.data.availableFonts;
self.fallbackFont = message.data.fallbackFont;
self.lazyFileLoading = message.data.lazyFileLoading;
self.debug = message.data.debug;
if (!hasNativeConsole && self.debug) {
console = makeCustomConsole();
Expand Down
6 changes: 4 additions & 2 deletions src/pre-worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,12 @@ Module["preRun"].push(function () {

self.subContent = null;

self.loadFontFile(".fallback-", self.fallbackFont);

//Module["FS"].mount(Module["FS"].filesystems.IDBFS, {}, '/fonts');
var fontFiles = self.fontFiles || [];
for (var i = 0; i < fontFiles.length; i++) {
Module["FS_createPreloadedFile"]("/fonts", 'font' + i + '-' + fontFiles[i].split('/').pop(), fontFiles[i], true, true);
self.loadFontFile('font' + i + '-', fontFiles[i]);
}
});

Expand All @@ -100,7 +102,7 @@ Module['onRuntimeInitialized'] = function () {

self.changed = Module._malloc(4);

self.octObj.initLibrary(screen.width, screen.height);
self.octObj.initLibrary(screen.width, screen.height, "/fonts/.fallback-" + self.fallbackFont.split('/').pop());
self.octObj.setDropAnimations(!!self.dropAllAnimations);
self.octObj.createTrack("/sub.ass");
self.ass_track = self.octObj.track;
Expand Down
4 changes: 4 additions & 0 deletions src/subtitles-octopus.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ var SubtitlesOctopus = function (options) {
self.canvasParent = null; // (internal) HTML canvas parent element
self.fonts = options.fonts || []; // Array with links to fonts used in sub (optional)
self.availableFonts = options.availableFonts || []; // Object with all available fonts (optional). Key is font name in lower case, value is link: {"arial": "/font1.ttf"}
self.fallbackFont = options.fallbackFont || 'default.woff2'; // URL to override fallback font, for example, with a CJK one. Default fallback font is Liberation Sans (Optional)
self.lazyFileLoading = options.lazyFileLoading || false; // Load fonts in a lazy way. Requires Access-Control-Expose-Headers for Accept-Ranges, Content-Length, and Content-Encoding. If Content-Encoding is compressed, file will be fully fetched instead of just a HEAD request.
self.onReadyEvent = options.onReady; // Function called when SubtitlesOctopus is ready (optional)
if (supportsWebAssembly) {
self.workerUrl = options.workerUrl || 'subtitles-octopus-worker.js'; // Link to WebAssembly worker
Expand Down Expand Up @@ -144,6 +146,8 @@ var SubtitlesOctopus = function (options) {
subContent: self.subContent,
fonts: self.fonts,
availableFonts: self.availableFonts,
fallbackFont: self.fallbackFont,
lazyFileLoading: self.lazyFileLoading,
debug: self.debug,
targetFps: self.targetFps,
libassMemoryLimit: self.libassMemoryLimit,
Expand Down

0 comments on commit 06edd4f

Please sign in to comment.