Skip to content

Commit

Permalink
Don't cache server requested glyphs in the local glyph ranges (#8657)
Browse files Browse the repository at this point in the history
* Use correct value for localIdeographFontFamily in Map#setStyle

* Ignore local glyph ranges when caching server requested glyphs

* Cache locally generated glyphs in GlyphManager
  • Loading branch information
Asheem Mamoowala authored Aug 20, 2019
1 parent 8f0998d commit 97ba78b
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 8 deletions.
23 changes: 16 additions & 7 deletions src/render/glyph_manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class GlyphManager {

glyph = this._tinySDF(entry, stack, id);
if (glyph) {
entry.glyphs[id] = glyph;
callback(null, {stack, id, glyph});
return;
}
Expand All @@ -81,7 +82,9 @@ class GlyphManager {
(err, response: ?{[number]: StyleGlyph | null}) => {
if (response) {
for (const id in response) {
entry.glyphs[+id] = response[+id];
if (!this._doesCharSupportLocalGlyph(+id)) {
entry.glyphs[+id] = response[+id];
}
}
}
for (const cb of requests) {
Expand Down Expand Up @@ -118,17 +121,23 @@ class GlyphManager {
});
}

_doesCharSupportLocalGlyph(id: number): boolean {
/* eslint-disable new-cap */
return !!this.localIdeographFontFamily &&
(isChar['CJK Unified Ideographs'](id) ||
isChar['Hangul Syllables'](id) ||
isChar['Hiragana'](id) ||
isChar['Katakana'](id));
/* eslint-enable new-cap */
}

_tinySDF(entry: Entry, stack: string, id: number): ?StyleGlyph {
const family = this.localIdeographFontFamily;
if (!family) {
return;
}
/* eslint-disable new-cap */
if (!isChar['CJK Unified Ideographs'](id) &&
!isChar['Hangul Syllables'](id) &&
!isChar['Hiragana'](id) &&
!isChar['Katakana'](id)
) { /* eslint-enable new-cap */

if (!this._doesCharSupportLocalGlyph(id)) {
return;
}

Expand Down
2 changes: 1 addition & 1 deletion src/ui/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -965,7 +965,7 @@ class Map extends Camera {
* @see [Change a map's style](https://www.mapbox.com/mapbox-gl-js/example/setstyle/)
*/
setStyle(style: StyleSpecification | string | null, options?: {diff?: boolean} & StyleOptions) {
options = extend({}, { localIdeographFontFamily: defaultOptions.localIdeographFontFamily}, options);
options = extend({}, { localIdeographFontFamily: this._localIdeographFontFamily}, options);

if ((options.diff !== false && options.localIdeographFontFamily === this._localIdeographFontFamily) && this.style && style) {
this._diffStyle(style, options);
Expand Down
60 changes: 60 additions & 0 deletions test/unit/render/glyph_manager.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,41 @@ test('GlyphManager requests remote CJK PBF', (t) => {
});
});

test('GlyphManager does not cache CJK chars that should be rendered locally', (t) => {
t.stub(GlyphManager, 'loadGlyphRange').callsFake((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];
}
setImmediate(() => callback(null, overlappingGlyphs));
});
t.stub(GlyphManager, 'TinySDF').value(class {
// Return empty 30x30 bitmap (24 fontsize + 3 * 2 buffer)
draw() {
return new Uint8ClampedArray(900);
}
});
const manager = new GlyphManager((url) => ({url}), 'sans-serif');
manager.setURL('https://localhost/fonts/v1/{fontstack}/{range}.pbf');

//Request char that overlaps Katakana range
manager.getGlyphs({'Arial Unicode MS': [0x3005]}, (err, glyphs) => {
t.ifError(err);
t.notEqual(glyphs['Arial Unicode MS'][0x3005], null);
//Request char from Katakana range (te)
manager.getGlyphs({'Arial Unicode MS': [0x30C6]}, (err, glyphs) => {
t.ifError(err);
const glyph = glyphs['Arial Unicode MS'][0x30c6];
//Ensure that te is locally generated.
t.equal(glyph.bitmap.height, 30);
t.equal(glyph.bitmap.width, 30);
t.end();
});
});
});

test('GlyphManager generates CJK PBF locally', (t) => {
t.stub(GlyphManager, 'TinySDF').value(class {
// Return empty 30x30 bitmap (24 fontsize + 3 * 2 buffer)
Expand Down Expand Up @@ -98,3 +133,28 @@ test('GlyphManager generates Hiragana PBF locally', (t) => {
t.end();
});
});

test('GlyphManager caches locally generated glyphs', (t) => {
let drawCallCount = 0;
t.stub(GlyphManager, 'TinySDF').value(class {
// Return empty 30x30 bitmap (24 fontsize + 3 * 2 buffer)
draw() {
drawCallCount++;
return new Uint8ClampedArray(900);
}
});

const manager = new GlyphManager((url) => ({url}), 'sans-serif');
manager.setURL('https://localhost/fonts/v1/{fontstack}/{range}.pbf');

// Katakana letter te
manager.getGlyphs({'Arial Unicode MS': [0x30c6]}, (err, glyphs) => {
t.ifError(err);
t.equal(glyphs['Arial Unicode MS'][0x30c6].metrics.advance, 24);
manager.getGlyphs({'Arial Unicode MS': [0x30c6]}, () => {
t.equal(drawCallCount, 1);
t.end();
});
});
});

0 comments on commit 97ba78b

Please sign in to comment.