Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add fallback character when a character is missing from custom font #13070

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
35 changes: 28 additions & 7 deletions src/render/glyph_manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,14 @@ class GlyphManager {
// Multiple fontstacks may share the same local glyphs, so keep an index
// into the glyphs based soley on font weight
localGlyphs: {[_: string]: {glyphs: {[id: number]: StyleGlyph | null}, ascender: ?number, descender: ?number}};
enableFallbackGlyph: ?boolean
urls: {[scope: string]: ?string};

// exposed as statics to enable stubbing in unit tests
static loadGlyphRange: typeof loadGlyphRange;
static TinySDF: Class<TinySDF>;

constructor(requestManager: RequestManager, localGlyphMode: number, localFontFamily: ?string) {
constructor(requestManager: RequestManager, localGlyphMode: number, localFontFamily: ?string, enableFallbackGlyph: ?boolean) {
this.requestManager = requestManager;
this.localGlyphMode = localGlyphMode;
this.localFontFamily = localFontFamily;
Expand All @@ -78,6 +79,7 @@ class GlyphManager {
'500': {},
'900': {}
};
this.enableFallbackGlyph = enableFallbackGlyph;
}

setURL(url: ?string, scope: string) {
Expand All @@ -91,8 +93,13 @@ class GlyphManager {
const url = this.urls[scope] || config.GLYPHS_URL;

for (const stack in glyphs) {
let doesCharSupportFallbackGlyphRange = false;
for (const id of glyphs[stack]) {
all.push({stack, id});
if (this.localGlyphMode !== LocalGlyphMode.all && !!this.enableFallbackGlyph && id >= 0 && id <= 255) doesCharSupportFallbackGlyphRange = true;
}
if (this.localGlyphMode !== LocalGlyphMode.all && !!this.enableFallbackGlyph && !doesCharSupportFallbackGlyphRange) {
all.push({stack, id: 63});
}
}

Expand Down Expand Up @@ -171,15 +178,29 @@ class GlyphManager {
// Clone the glyph so that our own copy of its ArrayBuffer doesn't get transferred.
if (result[stack] === undefined) result[stack] = {};
if (result[stack].glyphs === undefined) result[stack].glyphs = {};
result[stack].glyphs[id] = glyph && {
id: glyph.id,
bitmap: glyph.bitmap.clone(),
metrics: glyph.metrics
};
if (glyph) {
result[stack].glyphs[id] = {
id: glyph.id,
bitmap: glyph.bitmap.clone(),
metrics: glyph.metrics,
};
} else if (this.enableFallbackGlyph) {
const fallbackGlyph = this.entries[stack].glyphs[63];
if (fallbackGlyph) {
result[stack].glyphs[id] = {
id,
bitmap: fallbackGlyph.bitmap.clone(),
metrics: fallbackGlyph.metrics,
};
} else {
result[stack].glyphs[id] = null;
}
} else {
result[stack].glyphs[id] = null;
}
result[stack].ascender = this.entries[stack].ascender;
result[stack].descender = this.entries[stack].descender;
}

callback(null, result);
}
});
Expand Down
3 changes: 2 additions & 1 deletion src/style/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ export type StyleOptions = {
validate?: boolean,
localFontFamily?: ?string,
localIdeographFontFamily?: string,
enableFallbackGlyph?: boolean,

dispatcher?: Dispatcher,
imageManager?: ImageManager,
Expand Down Expand Up @@ -306,7 +307,7 @@ class Style extends Evented {
options.localFontFamily ?
LocalGlyphMode.all :
(options.localIdeographFontFamily ? LocalGlyphMode.ideographs : LocalGlyphMode.none),
options.localFontFamily || options.localIdeographFontFamily);
options.localFontFamily || options.localIdeographFontFamily, options.enableFallbackGlyph);
}

if (options.modelManager) {
Expand Down
11 changes: 8 additions & 3 deletions src/ui/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ const defaultOptions = {
maxTileCacheSize: null,
localIdeographFontFamily: 'sans-serif',
localFontFamily: null,
enableFallbackGlyph: false,
transformRequest: null,
accessToken: null,
fadeDuration: 300,
Expand Down Expand Up @@ -301,6 +302,7 @@ const defaultOptions = {
* @param {string} [options.localFontFamily=null] Defines a CSS
* font-family for locally overriding generation of all glyphs. Font settings from the map's style will be ignored, except for font-weight keywords (light/regular/medium/bold).
* If set, this option overrides the setting in localIdeographFontFamily.
* @param {boolean} [options.enableFallbackGlyph=false] If `true`, will show the fallback character ? In place of characters which are missing from custom fonts.
* @param {RequestTransformFunction} [options.transformRequest=null] A callback run before the Map makes a request for an external URL. The callback can be used to modify the url, set headers, or set the credentials property for cross-origin requests.
* Expected to return a {@link RequestParameters} object with a `url` property and optionally `headers` and `credentials` properties.
* @param {boolean} [options.collectResourceTiming=false] If `true`, Resource Timing API information will be collected for requests made by GeoJSON and Vector Tile web workers (this information is normally inaccessible from the main Javascript thread). Information will be returned in a `resourceTiming` property of relevant `data` events.
Expand Down Expand Up @@ -400,6 +402,7 @@ class Map extends Camera {
_mapId: number;
_localIdeographFontFamily: string;
_localFontFamily: ?string;
_enableFallbackGlyph: ?boolean;
_requestManager: RequestManager;
_locale: Object;
_removed: boolean;
Expand Down Expand Up @@ -611,10 +614,11 @@ class Map extends Camera {

this._localFontFamily = options.localFontFamily;
this._localIdeographFontFamily = options.localIdeographFontFamily;
this._enableFallbackGlyph = options.enableFallbackGlyph;

if (options.style || !options.testMode) {
const style = options.style || config.DEFAULT_STYLE;
this.setStyle(style, {localFontFamily: this._localFontFamily, localIdeographFontFamily: this._localIdeographFontFamily});
this.setStyle(style, {localFontFamily: this._localFontFamily, localIdeographFontFamily: this._localIdeographFontFamily, enableFallbackGlyph: this._enableFallbackGlyph});
}

if (options.projection) {
Expand Down Expand Up @@ -1940,16 +1944,17 @@ class Map extends Camera {
* @see [Example: Change a map's style](https://www.mapbox.com/mapbox-gl-js/example/setstyle/)
*/
setStyle(style: StyleSpecification | string | null, options?: {diff?: boolean} & StyleOptions): this {
options = extend({}, {localIdeographFontFamily: this._localIdeographFontFamily, localFontFamily: this._localFontFamily}, options);
options = extend({}, {localIdeographFontFamily: this._localIdeographFontFamily, localFontFamily: this._localFontFamily, enableFallbackGlyph: this._enableFallbackGlyph}, options);

if ((options.diff !== false &&
options.localIdeographFontFamily === this._localIdeographFontFamily &&
options.localFontFamily === this._localFontFamily) && this.style && style) {
options.localFontFamily === this._localFontFamily && options.enableFallbackGlyph === this._enableFallbackGlyph) && this.style && style) {
this._diffStyle(style, options);
return this;
} else {
this._localIdeographFontFamily = options.localIdeographFontFamily;
this._localFontFamily = options.localFontFamily;
this._enableFallbackGlyph = options.enableFallbackGlyph;
return this._updateStyle(style, options);
}
}
Expand Down