Skip to content

Commit

Permalink
Support loading font assets in data URLs (#8898)
Browse files Browse the repository at this point in the history
  • Loading branch information
SuperSodaSea authored and bigtimebuddy committed Dec 12, 2022
1 parent e1ea3a7 commit e1da86c
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 41 deletions.
18 changes: 12 additions & 6 deletions packages/assets/src/loader/parsers/loadWebFont.ts
@@ -1,13 +1,22 @@
import { extensions, ExtensionType, settings, utils } from '@pixi/core';
import { checkDataUrl } from '../../utils/checkDataUrl';
import { checkExtension } from '../../utils/checkExtension';
import { LoaderParserPriority } from './LoaderParser';

import type { LoadAsset } from '../types';
import type { LoaderParser } from './LoaderParser';

const validWeights = ['normal', 'bold',
const validWeights = [
'normal', 'bold',
'100', '200', '300', '400', '500', '600', '700', '800', '900',
];
const validFonts = ['woff', 'woff2', 'ttf', 'otf'];
const validFontExtensions = ['.ttf', '.otf', '.woff', '.woff2'];
const validFontMIMEs = [
'font/ttf',
'font/otf',
'font/woff',
'font/woff2',
];

export type LoadFontData = {
family: string;
Expand Down Expand Up @@ -51,10 +60,7 @@ export const loadWebFont = {

test(url: string): boolean
{
const tempURL = url.split('?')[0];
const extension = tempURL.split('.').pop();

return validFonts.includes(extension);
return checkDataUrl(url, validFontMIMEs) || checkExtension(url, validFontExtensions);
},

async load(url: string, options?: LoadAsset<LoadFontData>): Promise<FontFace | FontFace[]>
Expand Down
24 changes: 10 additions & 14 deletions packages/assets/src/loader/parsers/textures/loadTexture.ts
@@ -1,15 +1,22 @@
import { BaseTexture, extensions, ExtensionType, settings, utils } from '@pixi/core';
import { checkDataUrl } from '../../../utils/checkDataUrl';
import { checkExtension } from '../../../utils/checkExtension';
import { LoaderParserPriority } from '../LoaderParser';
import { WorkerManager } from '../WorkerManager';
import { checkExtension } from './utils/checkExtension';
import { createTexture } from './utils/createTexture';

import type { IBaseTextureOptions, Texture } from '@pixi/core';
import type { Loader } from '../../Loader';
import type { LoadAsset } from '../../types';
import type { LoaderParser } from '../LoaderParser';

const validImages = ['.jpg', '.png', '.jpeg', '.avif', '.webp'];
const validImageExtensions = ['.jpeg', '.jpg', '.png', '.webp', '.avif'];
const validImageMIMEs = [
'image/jpeg',
'image/png',
'image/webp',
'image/avif',
];

/**
* Returns a promise that resolves an ImageBitmaps.
Expand Down Expand Up @@ -51,18 +58,7 @@ export const loadTextures = {

test(url: string): boolean
{
let isValidBase64Suffix = false;

for (let i = 0; i < validImages.length; i++)
{
if (url.startsWith(`data:image/${validImages[i].slice(1)}`))
{
isValidBase64Suffix = true;
break;
}
}

return isValidBase64Suffix || checkExtension(url, validImages);
return checkDataUrl(url, validImageMIMEs) || checkExtension(url, validImageExtensions);
},

async load(url: string, asset: LoadAsset<IBaseTextureOptions>, loader: Loader): Promise<Texture>
Expand Down
1 change: 0 additions & 1 deletion packages/assets/src/loader/parsers/textures/utils/index.ts
@@ -1,2 +1 @@
export * from './checkExtension';
export * from './createTexture';
14 changes: 14 additions & 0 deletions packages/assets/src/utils/checkDataUrl.ts
@@ -0,0 +1,14 @@
export function checkDataUrl(url: string, mimes: string | string[]): boolean
{
if (Array.isArray(mimes))
{
for (const mime of mimes)
{
if (url.startsWith(`data:${mime}`)) return true;
}

return false;
}

return url.startsWith(`data:${mimes}`);
}
File renamed without changes.
2 changes: 2 additions & 0 deletions packages/assets/src/utils/index.ts
@@ -1,3 +1,5 @@
export * from './checkDataUrl';
export * from './checkExtension';
export * from './convertToList';
export * from './createStringVariations';
export * from './isSingleItem';
39 changes: 19 additions & 20 deletions packages/assets/test/assets.tests.ts
Expand Up @@ -334,30 +334,29 @@ describe('Assets', () =>
expect(assets.bunny.baseTexture).toBe(null);
});

it('should load PNG base64 assets', async () =>
it('should load PNG assets from data URL', async () =>
{
// Other formats (JPG, JPEG, WEBP, AVIF) can be added similarly.
let bunnyBase64 = `
data:image/png;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAkGBggGBQkIBwgKCQkKDRYODQwMDRoTFBAWHxwhIB8c
Hh4jJzIqIyUvJR4eKzssLzM1ODg4ISo9QTw2QTI3ODX/2wBDAQkKCg0LDRkODhk1JB4kNTU1NTU1NTU1NTU1NTU1NTU1NTU1NT
U1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTX/wgARCAAlABoDAREAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABgUHBP/E
ABkBAAMBAQEAAAAAAAAAAAAAAAIDBAUBBv/aAAwDAQACEAMQAAAAfoMjG9G5byxWYwUHfPaNTTmebMAqZ1zJphvFntQwkNP49f
dWrUdeIEs1xcBAWmGH/8QANRAAAQMCBAQDAg8AAAAAAAAAAgEDBAURAAYSEwcUIWEQFSIxUjI0NkJFVFVicXWBoqTCw//aAAgB
AQABPwDiRsHGobM3rBfqoBKb+abaNOlYk/Eb4qz8Cmee0mhjsQpnJIwywC7J6XV5nsl27It/h4y6xSIHEFlnLjLLEN+mPG8DCa
BMxcZ037oh+Gd810nMgQIlIkrKciTleds0aBoRp0LoappLqSexcMsTtp0xjPSmWiu6+KtiLaGSoKKikirbsmMpVFqhV2NLqLjp
gEN5g3WoxuKpkTCp6ARVS+2eEz7lv7bgB9x19AMeyivVFxxGyrScswoE6jxliPvz9o7PHo0K06VkBV0j1HFAybCqFGalSTdU3e
vpW1sUygRJ+fjo07dditRX3LA8bSqYG0KLcFRfYZYHIGWg+g4B93GdZfqS9Vxxk+T9J/M/8H8QuKjNBY5BX4jmz7xpcMZCqPm3
EMZmtHN+myTund1jw4zhbIwzvqEsH9Hv3Qm/74oFO8oy5TqfubvKRWmNdratIoN7YyRTdji/mj1/E9f8lxHv228P/8QAHxEAAg
IDAAMBAQAAAAAAAAAAAQIAAwQREgUQIRRR/9oACAECAQE/AL2CoWJi5VfJJaY1osJ0dzqZ1qikgwVJYpcHWp426sM4Hydj+zMr
U0kzGwBbV0TPHY6qz7nCzL+0tqUfqRNBfk8cGBfv1YNrqARF0xPr/8QAHhEAAgICAwEBAAAAAAAAAAAAAQIAAxESBBAhMTL/2g
AIAQMBAT8AQEnAgqckSxWA9646HfML6kLOUjEAzQyh23xLeQVbAl9hKjE3Mp/Yli1M32cnGAB0h9hhPnX/2Q==
// Other formats (JPEG, WEBP, AVIF) can be added similarly.
let bunnyDataURL = `
data:image/png;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAkGBggGBQkIBwgKCQkKDRYODQwMDRoTFBAWHxwhIB8cHh
4jJzIqIyUvJR4eKzssLzM1ODg4ISo9QTw2QTI3ODX/2wBDAQkKCg0LDRkODhk1JB4kNTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NT
U1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTX/wgARCAAlABoDAREAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABgUHBP/EABkBAA
MBAQEAAAAAAAAAAAAAAAIDBAUBBv/aAAwDAQACEAMQAAAAfoMjG9G5byxWYwUHfPaNTTmebMAqZ1zJphvFntQwkNP49fdWrUdeIE
s1xcBAWmGH/8QANRAAAQMCBAQDAg8AAAAAAAAAAgEDBAURAAYSEwcUIWEQFSIxUjI0NkJFVFVicXWBoqTCw//aAAgBAQABPwDiRs
HGobM3rBfqoBKb+abaNOlYk/Eb4qz8Cmee0mhjsQpnJIwywC7J6XV5nsl27It/h4y6xSIHEFlnLjLLEN+mPG8DCaBMxcZ037oh+G
d810nMgQIlIkrKciTleds0aBoRp0LoappLqSexcMsTtp0xjPSmWiu6+KtiLaGSoKKikirbsmMpVFqhV2NLqLjpgEN5g3WoxuKpkT
Cp6ARVS+2eEz7lv7bgB9x19AMeyivVFxxGyrScswoE6jxliPvz9o7PHo0K06VkBV0j1HFAybCqFGalSTdU3evpW1sUygRJ+fjo07
dditRX3LA8bSqYG0KLcFRfYZYHIGWg+g4B93GdZfqS9Vxxk+T9J/M/8H8QuKjNBY5BX4jmz7xpcMZCqPm3EMZmtHN+myTund1jw4
zhbIwzvqEsH9Hv3Qm/74oFO8oy5TqfubvKRWmNdratIoN7YyRTdji/mj1/E9f8lxHv228P/8QAHxEAAgIDAAMBAQAAAAAAAAAAAQ
IAAwQREgUQIRRR/9oACAECAQE/AL2CoWJi5VfJJaY1osJ0dzqZ1qikgwVJYpcHWp426sM4Hydj+zMrU0kzGwBbV0TPHY6qz7nCzL
+0tqUfqRNBfk8cGBfv1YNrqARF0xPr/8QAHhEAAgICAwEBAAAAAAAAAAAAAQIAAxESBBAhMTL/2gAIAQMBAT8AQEnAgqckSxWA96
46HfML6kLOUjEAzQyh23xLeQVbAl9hKjE3Mp/Yli1M32cnGAB0h9hhPnX/2Q==
`;

// to prevent eslint max-len warning
bunnyBase64 = bunnyBase64.replace(/\s/g, '');
// Prevent eslint max-len warning
bunnyDataURL = bunnyDataURL.replace(/\s/g, '');

Assets.add('bunny', bunnyBase64);
const bunny = await Assets.load('bunny');
const bunny = await Assets.load(bunnyDataURL);

expect(bunny).toBeInstanceOf(Texture);
});
Expand Down

0 comments on commit e1da86c

Please sign in to comment.