mirror of
https://github.com/slint-ui/slint.git
synced 2025-12-23 09:19:32 +00:00
- Bundle translations for WASM/Android only (not for native builds) - Load Noto Sans CJK fonts dynamically from GitHub at runtime - Implement register_font_from_memory() with Result<FontHandle, RegisterFontError> - Make API automatically available with std feature (no explicit feature flag needed) - Export load_font_from_bytes() for WASM font loading from JavaScript - Change from wasm_bindgen(start) to explicit main() call for better control Fonts are loaded before app initialization to ensure proper CJK text rendering across all major browsers without bundling font files. Native builds load translations from lang/ directory at runtime. WASM/Android builds bundle translations at compile time and detect browser/system language automatically. API is now available when std feature is enabled, since we always have fontique with std. No need for experimental-register-font feature.
169 lines
6 KiB
HTML
169 lines
6 KiB
HTML
<!DOCTYPE html>
|
|
|
|
<!-- Copyright © SixtyFPS GmbH <info@slint.dev> -->
|
|
<!-- SPDX-License-Identifier: MIT -->
|
|
|
|
<html>
|
|
<!--
|
|
This is a static html file used to display the wasm build.
|
|
In order to generate the build
|
|
- uncomment the #wasm# lines in Cargo.toml
|
|
- Run in this directory:
|
|
SLINT_STYLE=fluent wasm-pack build --release --out-dir pkg/fluent --target web
|
|
SLINT_STYLE=material wasm-pack build --release --out-dir pkg/material --target web
|
|
SLINT_STYLE=cupertino wasm-pack build --release --out-dir pkg/cupertino --target web
|
|
SLINT_STYLE=cosmic wasm-pack build --release --out-dir pkg/cosmic --target web
|
|
-->
|
|
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>Slint Widget Gallery Demo (Web Assembly version)</title>
|
|
<link rel="stylesheet" href="https://slint.dev/css/demos-v1.css">
|
|
</head>
|
|
|
|
<body>
|
|
<h1>Slint Gallery</h1>
|
|
<p>This is the <a href="https://slint.dev">Slint</a> UI Widget Gallery Demo compiled to WebAssembly. It
|
|
demonstrates
|
|
different re-usable graphical
|
|
elements.</p>
|
|
|
|
<div id="spinner" style="position: relative;">
|
|
<div class="spinner">Loading...</div>
|
|
</div>
|
|
<p>Select style
|
|
<select id="style-selection">
|
|
<option value="fluent">Fluent</option>
|
|
<option value="material">Material</option>
|
|
<option value="cupertino">Cupertino</option>
|
|
<option value="cosmic">Cosmic</option>
|
|
</select>
|
|
</p>
|
|
<div id="canvas-parent"></div>
|
|
<p class="links">
|
|
<a href="https://github.com/slint-ui/slint/blob/master/examples/gallery/gallery.slint">
|
|
View Source Code on GitHub</a> -
|
|
<a href="https://slint.dev/editor?load_demo=examples/gallery/gallery.slint">
|
|
Open in SlintPad
|
|
</a>
|
|
</p>
|
|
<script type="module">
|
|
var galleries = [];
|
|
var currentGallery = undefined;
|
|
|
|
// Get Noto CJK font URL from GitHub for the detected language
|
|
function getNotoFontUrl(lang) {
|
|
const langCode = lang.split('-')[0].toLowerCase();
|
|
|
|
// Direct URLs to OTF files from Noto CJK GitHub repository (using raw.githubusercontent.com for CORS)
|
|
const fontMap = {
|
|
'ja': 'https://raw.githubusercontent.com/notofonts/noto-cjk/main/Sans/OTF/Japanese/NotoSansCJKjp-Regular.otf',
|
|
// 'zh': 'https://raw.githubusercontent.com/notofonts/noto-cjk/main/Sans/OTF/SimplifiedChinese/NotoSansCJKsc-Regular.otf',
|
|
// 'ko': 'https://raw.githubusercontent.com/notofonts/noto-cjk/main/Sans/OTF/Korean/NotoSansCJKkr-Regular.otf',
|
|
};
|
|
|
|
return fontMap[langCode];
|
|
}
|
|
|
|
// Fetch font from GitHub
|
|
async function fetchFont(fontUrl) {
|
|
const fontResponse = await fetch(fontUrl);
|
|
if (!fontResponse.ok) {
|
|
throw new Error(`HTTP ${fontResponse.status}: ${fontResponse.statusText}`);
|
|
}
|
|
return await fontResponse.arrayBuffer();
|
|
}
|
|
|
|
// Load font for the detected language
|
|
async function loadFontForLanguage(module, lang) {
|
|
const fontUrl = getNotoFontUrl(lang);
|
|
|
|
if (fontUrl) {
|
|
try {
|
|
const fontData = await fetchFont(fontUrl);
|
|
const uint8Array = new Uint8Array(fontData);
|
|
const result = await module.load_font_from_bytes(uint8Array);
|
|
} catch (error) {
|
|
console.error(`Failed to load font for language ${lang}:`, error);
|
|
}
|
|
}
|
|
}
|
|
|
|
function initGallery(gallery) {
|
|
document.getElementById("spinner").hidden = false;
|
|
|
|
if (currentGallery !== undefined) {
|
|
let currentGalleryCanvas = document.getElementById("canvas");
|
|
|
|
// remove old canvas and unload window
|
|
if (currentGalleryCanvas != undefined) {
|
|
document.getElementById("canvas-parent").removeChild(currentGalleryCanvas);
|
|
}
|
|
}
|
|
|
|
if (galleries[gallery] !== undefined) {
|
|
document.getElementById("canvas-parent").appendChild(galleries[gallery]);
|
|
document.getElementById("spinner").hidden = true;
|
|
} else {
|
|
import(gallery).then(async module => {
|
|
let canvas = document.createElement("canvas");
|
|
canvas.id = "canvas";
|
|
canvas.dataset.slintAutoResizeToPreferred = "true";
|
|
currentGallery = gallery;
|
|
galleries[gallery] = canvas;
|
|
|
|
document.getElementById("canvas-parent").appendChild(canvas);
|
|
|
|
// Initialize WASM module first
|
|
await module.default();
|
|
|
|
// Detect browser language and load appropriate font
|
|
const browserLang = (navigator.languages && navigator.languages[0]) || navigator.language || navigator.userLanguage || 'en';
|
|
await loadFontForLanguage(module, browserLang);
|
|
|
|
// Start the application
|
|
module.main();
|
|
|
|
document.getElementById("canvas").hidden = false;
|
|
document.getElementById("spinner").hidden = true;
|
|
}).catch(error => {
|
|
console.error('Failed to initialize gallery:', error);
|
|
document.getElementById("spinner").hidden = true;
|
|
});
|
|
}
|
|
}
|
|
|
|
var styleSelection = document.getElementById("style-selection");
|
|
|
|
function loadGallery() {
|
|
var selectedStyle = ".\/pkg\/" + styleSelection[styleSelection.selectedIndex].value + "\/gallery.js";
|
|
initGallery(selectedStyle);
|
|
}
|
|
|
|
styleSelection.onchange = loadGallery;
|
|
|
|
window.addEventListener('load', () => {
|
|
const urlParams = new URLSearchParams(window.location.search);
|
|
const style = urlParams.get('style');
|
|
if (style) {
|
|
document.getElementById('style-selection').value = style.split(',')[0];
|
|
} else {
|
|
const userAgent = window.navigator.userAgent.toLowerCase();
|
|
let defaultStyle = '';
|
|
if (userAgent.indexOf('mac') !== -1 || userAgent.indexOf('iphone') !== -1 || userAgent.indexOf('ipad') !== -1) {
|
|
defaultStyle = 'cupertino';
|
|
} else if (userAgent.indexOf('windows') !== -1) {
|
|
defaultStyle = 'fluent';
|
|
} else if (userAgent.indexOf('android') !== -1) {
|
|
defaultStyle = 'material';
|
|
}
|
|
if (defaultStyle) {
|
|
document.getElementById('style-selection').value = defaultStyle;
|
|
}
|
|
}
|
|
loadGallery();
|
|
}, false);
|
|
</script>
|
|
</body>
|
|
|
|
</html>
|