s2maps-gpu
Version:
S2 Maps GPU - An open source, high-performance, and GPU-accelerated map engine for rendering large-scale, interactive maps.
128 lines (127 loc) • 4.25 kB
JavaScript
/**
* # ImageSource
*
* ## Description
* A collection of images relating to a single source
*/
export default class ImageSource {
active = true;
name;
path;
fileType = 'png';
metadata = {};
session;
texturePack;
/**
* @param name - the name of the source
* @param path - the path to the source
* @param texturePack - the texture pack to store the glyphs/images into
* @param session - the session
* @param fileType - the file type
*/
constructor(name, path, texturePack, session, fileType) {
this.name = name;
this.path = path;
this.texturePack = texturePack;
this.session = session;
if (fileType !== undefined)
this.fileType = fileType;
}
/**
* Build the source
* @param _mapID - the id of the map to build for
* @returns the image metadata (we don't need to early ship this)
*/
async build(_mapID) {
return await undefined;
}
/**
* Add an image to the source collection
* @param mapID - the id of the map to build for
* @param name - the name of the image
* @param path - the path to the image
* @returns the image metadata if successful
*/
async addImage(mapID, name, path) {
const { metadata, texturePack } = this;
// grab the metadata and sprites
const data = await this._fetch(path, mapID).catch((err) => {
console.error(err);
return undefined;
});
// if either failed, stop their
if (data === undefined) {
this.active = false;
console.error(`Failed to fetch sprite source ${name}`);
}
else {
const imageMetadata = {
code: name,
texX: 0,
texY: 0,
texW: 0,
texH: 0,
xOffset: 0,
yOffset: 0,
width: 0,
height: 0,
advanceWidth: 0,
};
// prebuild the sprite sheet if possible
const image = await createImageBitmap(new Blob([data]), {
premultiplyAlpha: 'none',
imageOrientation: 'flipY',
});
// update metadata width and height
imageMetadata.width = image.width;
imageMetadata.height = image.height;
imageMetadata.texW = image.width;
imageMetadata.texH = image.height;
// get offsets from texturePack
const [offsetX, offsetY] = texturePack.addGlyph(imageMetadata.width, imageMetadata.height);
// update imageMetadata x and y
imageMetadata.texX = offsetX;
imageMetadata.texY = offsetY;
// store the metadata
metadata[name] = imageMetadata;
// ship the sprites to the map
const spriteImageMessage = {
type: 'spriteimage',
mapID,
name: this.name,
offsetX,
offsetY,
width: imageMetadata.width,
height: imageMetadata.height,
maxHeight: texturePack.height,
image,
};
postMessage(spriteImageMessage, [image]);
}
return { name: this.name, metadata };
}
/**
* Fetch an image
* @param path - the path to the image or metadata
* @param mapID - the id of the map
* @returns the image or metadata
*/
async _fetch(path, mapID) {
const { session } = this;
const headers = {};
if (session.hasAPIKey(mapID)) {
const Authorization = await session.requestSessionToken(mapID);
if (Authorization === 'failed')
return;
if (Authorization !== undefined)
headers.Authorization = Authorization;
}
const res = await fetch(path, { headers });
if (res.status !== 200 && res.status !== 206)
return;
if (path.endsWith('json') || res.headers.get('content-type') === 'application/json') {
return await res.json();
}
return (await res.arrayBuffer());
}
}