maplibre-gl
Version:
BSD licensed community fork of mapbox-gl, a WebGL interactive maps library
160 lines (132 loc) • 6.07 kB
text/typescript
import parseGlyphPBF from '../style/parse_glyph_pbf';
import GlyphManager from './glyph_manager';
import fs from 'fs';
import {RequestManager} from '../util/request_manager';
const glyphs = {};
for (const glyph of parseGlyphPBF(fs.readFileSync('./test/unit/assets/0-255.pbf'))) {
glyphs[glyph.id] = glyph;
}
const identityTransform = ((url) => ({url})) as any as RequestManager;
const createLoadGlyphRangeStub = () => {
return jest.spyOn(GlyphManager, 'loadGlyphRange').mockImplementation((stack, range, urlTemplate, transform, callback) => {
expect(stack).toBe('Arial Unicode MS');
expect(range).toBe(0);
expect(urlTemplate).toBe('https://localhost/fonts/v1/{fontstack}/{range}.pbf');
expect(transform).toBe(identityTransform);
setTimeout(() => callback(null, glyphs), 0);
});
};
const createGlyphManager = (font?) => {
const manager = new GlyphManager(identityTransform, font);
manager.setURL('https://localhost/fonts/v1/{fontstack}/{range}.pbf');
return manager;
};
afterEach(() => {
jest.clearAllMocks();
});
describe('GlyphManager', () => {
test('GlyphManager requests 0-255 PBF', done => {
createLoadGlyphRangeStub();
const manager = createGlyphManager();
manager.getGlyphs({'Arial Unicode MS': [55]}, (err, glyphs) => {
expect(err).toBeFalsy();
expect(glyphs['Arial Unicode MS']['55'].metrics.advance).toBe(12);
done();
});
});
test('GlyphManager doesn\'t request twice 0-255 PBF if a glyph is missing', done => {
const stub = createLoadGlyphRangeStub();
const manager = createGlyphManager();
manager.getGlyphs({'Arial Unicode MS': [0.5]}, (err) => {
expect(err).toBeFalsy();
expect(manager.entries['Arial Unicode MS'].ranges[0]).toBe(true);
expect(stub).toHaveBeenCalledTimes(1);
// We remove all requests as in getGlyphs code.
delete manager.entries['Arial Unicode MS'].requests[0];
manager.getGlyphs({'Arial Unicode MS': [0.5]}, (err) => {
expect(err).toBeFalsy();
expect(manager.entries['Arial Unicode MS'].ranges[0]).toBe(true);
expect(stub).toHaveBeenCalledTimes(1);
done();
});
});
});
test('GlyphManager requests remote CJK PBF', done => {
jest.spyOn(GlyphManager, 'loadGlyphRange').mockImplementation((stack, range, urlTemplate, transform, callback) => {
setTimeout(() => callback(null, glyphs), 0);
});
const manager = createGlyphManager();
manager.getGlyphs({'Arial Unicode MS': [0x5e73]}, (err, glyphs) => {
expect(err).toBeFalsy();
expect(glyphs['Arial Unicode MS'][0x5e73]).toBeNull(); // The fixture returns a PBF without the glyph we requested
done();
});
});
test('GlyphManager does not cache CJK chars that should be rendered locally', done => {
jest.spyOn(GlyphManager, 'loadGlyphRange').mockImplementation((stack, range, urlTemplate, transform, callback) => {
const overlappingGlyphs = {};
const start = range * 256;
const end = start + 256;
for (let i = start, j = 0; i < end; i++, j++) {
overlappingGlyphs[i] = glyphs[j];
}
setTimeout(() => callback(null, overlappingGlyphs), 0);
});
const manager = createGlyphManager('sans-serif');
//Request char that overlaps Katakana range
manager.getGlyphs({'Arial Unicode MS': [0x3005]}, (err, glyphs) => {
expect(err).toBeFalsy();
expect(glyphs['Arial Unicode MS'][0x3005]).not.toBeNull();
//Request char from Katakana range (te)
manager.getGlyphs({'Arial Unicode MS': [0x30C6]}, (err, glyphs) => {
expect(err).toBeFalsy();
const glyph = glyphs['Arial Unicode MS'][0x30c6];
//Ensure that te is locally generated.
expect(glyph.bitmap.height).toBe(6);
expect(glyph.bitmap.width).toBe(6);
done();
});
});
});
test('GlyphManager generates CJK PBF locally', done => {
const manager = createGlyphManager('sans-serif');
manager.getGlyphs({'Arial Unicode MS': [0x5e73]}, (err, glyphs) => {
expect(err).toBeFalsy();
expect(glyphs['Arial Unicode MS'][0x5e73].metrics.advance).toBe(1);
done();
});
});
test('GlyphManager generates Katakana PBF locally', done => {
const manager = createGlyphManager('sans-serif');
// Katakana letter te
manager.getGlyphs({'Arial Unicode MS': [0x30c6]}, (err, glyphs) => {
expect(err).toBeFalsy();
expect(glyphs['Arial Unicode MS'][0x30c6].metrics.advance).toBe(1);
done();
});
});
test('GlyphManager generates Hiragana PBF locally', done => {
const manager = createGlyphManager('sans-serif');
//Hiragana letter te
manager.getGlyphs({'Arial Unicode MS': [0x3066]}, (err, glyphs) => {
expect(err).toBeFalsy();
expect(glyphs['Arial Unicode MS'][0x3066].metrics.advance).toBe(1);
done();
});
});
test('GlyphManager caches locally generated glyphs', done => {
const manager = createGlyphManager('sans-serif');
const drawSpy = GlyphManager.TinySDF.prototype.draw = jest.fn().mockImplementation(() => {
return {data: new Uint8ClampedArray(900)} as any;
});
// Katakana letter te
manager.getGlyphs({'Arial Unicode MS': [0x30c6]}, (err, glyphs) => {
expect(err).toBeFalsy();
expect(glyphs['Arial Unicode MS'][0x30c6].metrics.advance).toBe(24);
manager.getGlyphs({'Arial Unicode MS': [0x30c6]}, () => {
expect(drawSpy).toHaveBeenCalledTimes(1);
done();
});
});
});
});