UNPKG

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
/** * # 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()); } }