Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Add fallback support to local ideograph font families #15255

Merged
merged 1 commit into from
Aug 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions platform/android/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to

## master

### Features
- Add fallback support to local ideograph font families [#15255](https://github.com/mapbox/mapbox-gl-native/pull/15255)

### Bug fixes

- Fixed an issue where it was possible to set the map’s content insets then tilt the map enough to see the horizon, causing performance issues [#15195](https://github.com/mapbox/mapbox-gl-native/pull/15195)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ public class MapboxConstants {

public static final boolean DEFAULT_MANAGE_SKU_TOKEN = true;

/**
* Default value for font fallback for local ideograph fonts
*/
public static final String DEFAULT_FONT = "sans-serif";

/**
* Unmeasured state
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.utils.BitmapUtils;
import com.mapbox.mapboxsdk.utils.FontUtils;

import java.util.Arrays;

Expand Down Expand Up @@ -70,7 +71,6 @@ public class MapboxMapOptions implements Parcelable {
private boolean prefetchesTiles = true;
private boolean zMediaOverlay = false;
private String localIdeographFontFamily;

private String apiBaseUri;

private boolean textureMode;
Expand Down Expand Up @@ -250,7 +250,7 @@ public static MapboxMapOptions createFromAttributes(@NonNull Context context, @N
String localIdeographFontFamily =
typedArray.getString(R.styleable.mapbox_MapView_mapbox_localIdeographFontFamily);
if (localIdeographFontFamily == null) {
localIdeographFontFamily = "sans-serif";
localIdeographFontFamily = MapboxConstants.DEFAULT_FONT;
}
mapboxMapOptions.localIdeographFontFamily(localIdeographFontFamily);

Expand Down Expand Up @@ -637,14 +637,33 @@ public MapboxMapOptions crossSourceCollisions(boolean crossSourceCollisions) {
* <p>
* The font family argument is passed to {@link android.graphics.Typeface#create(String, int)}.
* Default system fonts are defined in &#x27;/system/etc/fonts.xml&#x27;
* Default font for local ideograph font family is "sans-serif".
* Default font for local ideograph font family is {@link MapboxConstants#DEFAULT_FONT}.
*
* @param fontFamily font family for local ideograph generation.
* @return This
*/
@NonNull
public MapboxMapOptions localIdeographFontFamily(String fontFamily) {
this.localIdeographFontFamily = fontFamily;
this.localIdeographFontFamily = FontUtils.extractValidFont(fontFamily);
return this;
}

/**
* Set a font family from range of font families for generating glyphs locally for ideographs in the
tobrun marked this conversation as resolved.
Show resolved Hide resolved
* &#x27;CJK Unified Ideographs&#x27; and &#x27;Hangul Syllables&#x27; ranges. The first matching font
* will be selected. If no valid font found, it defaults to {@link MapboxConstants#DEFAULT_FONT}.
* <p>
* The font families are checked against the default system fonts defined in
* &#x27;/system/etc/fonts.xml&#x27; Default font for local ideograph font family is
* {@link MapboxConstants#DEFAULT_FONT}.
* </p>
*
* @param fontFamilies an array of font families for local ideograph generation.
* @return This
*/
@NonNull
public MapboxMapOptions localIdeographFontFamily(String... fontFamilies) {
this.localIdeographFontFamily = FontUtils.extractValidFont(fontFamilies);
return this;
}

Expand Down Expand Up @@ -942,7 +961,7 @@ public int getForegroundLoadColor() {
/**
* Returns the font-family for locally overriding generation of glyphs in the
* &#x27;CJK Unified Ideographs&#x27; and &#x27;Hangul Syllables&#x27; ranges.
* Default font for local ideograph font family is "sans-serif".
* Default font for local ideograph font family is {@link MapboxConstants#DEFAULT_FONT}.
*
* @return Local ideograph font family name.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,20 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.R;
import com.mapbox.mapboxsdk.attribution.AttributionLayout;
import com.mapbox.mapboxsdk.attribution.AttributionMeasure;
import com.mapbox.mapboxsdk.attribution.AttributionParser;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
import com.mapbox.mapboxsdk.log.Logger;
import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.maps.TelemetryDefinition;
import com.mapbox.mapboxsdk.storage.FileSource;
import com.mapbox.mapboxsdk.utils.FontUtils;
import com.mapbox.mapboxsdk.utils.ThreadUtils;

/**
Expand Down Expand Up @@ -98,7 +101,7 @@ public static class Options {
private LatLngBounds region;
private CameraPosition cameraPosition;
private boolean showLogo = true;
private String localIdeographFontFamily = "sans-serif";
private String localIdeographFontFamily = MapboxConstants.DEFAULT_FONT;
private String apiBaseUrl;

/**
Expand Down Expand Up @@ -182,14 +185,31 @@ public Options withLogo(boolean showLogo) {
* <p>
* The font family argument is passed to {@link android.graphics.Typeface#create(String, int)}.
* Default system fonts are defined in &#x27;/system/etc/fonts.xml&#x27;
* Default font for local ideograph font family is "sans-serif".
*
* Default font for local ideograph font family is {@link MapboxConstants#DEFAULT_FONT}.
* </p>
* @param fontFamily font family for local ideograph generation.
* @return the mutated {@link Options}
*/
@NonNull
public Options withLocalIdeographFontFamily(String fontFamily) {
this.localIdeographFontFamily = fontFamily;
this.localIdeographFontFamily = FontUtils.extractValidFont(fontFamily);
return this;
}

/**
* Set a font family from range of font families for generating glyphs locally for ideographs in the
* &#x27;CJK Unified Ideographs&#x27; and &#x27;Hangul Syllables&#x27; ranges.
* <p>
* The font families are checked against the default system fonts defined in
* &#x27;/system/etc/fonts.xml&#x27;. Default font for local ideograph font family is
* {@link MapboxConstants#DEFAULT_FONT}.
* </p>
* @param fontFamilies font families for local ideograph generation.
* @return the mutated {@link Options}
*/
@NonNull
public Options withLocalIdeographFontFamily(String... fontFamilies) {
this.localIdeographFontFamily = FontUtils.extractValidFont(fontFamilies);
return this;
}

Expand Down Expand Up @@ -274,7 +294,7 @@ public CameraPosition getCameraPosition() {

/**
* @return the font family used for locally generating ideographs,
* Default font for local ideograph font family is "sans-serif".
* Default font for local ideograph font family is {@link MapboxConstants#DEFAULT_FONT}.
*/
public String getLocalIdeographFontFamily() {
return localIdeographFontFamily;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.mapbox.mapboxsdk.utils;

import android.graphics.Typeface;

import com.mapbox.mapboxsdk.MapStrictMode;
import com.mapbox.mapboxsdk.log.Logger;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static com.mapbox.mapboxsdk.constants.MapboxConstants.DEFAULT_FONT;

/**
* Utility class to select a font from a range of font names based on the availability of fonts on the device.
*/
public class FontUtils {

private static final String TAG = "Mbgl-FontUtils";

private FontUtils() {
// no instance
}

/**
* Select a font from a range of font names to match the availability of fonts on the device.
*
* @param fontNames the range of font names to select from
* @return the selected fon
*/
public static String extractValidFont(String... fontNames) {
if (fontNames == null) {
return null;
}

List<String> validFonts = getAvailableFonts();
for (String fontName : fontNames) {
if (validFonts.contains(fontName)) {
return fontName;
}
}

Logger.i(TAG, String.format(
"Couldn't map font family for local ideograph, using %s instead", DEFAULT_FONT)
);
return DEFAULT_FONT;
}

private static List<String> getAvailableFonts() {
List<String> fonts = new ArrayList<>();
try {
Typeface typeface = Typeface.create(Typeface.DEFAULT, Typeface.NORMAL);
Field f = Typeface.class.getDeclaredField("sSystemFontMap");
f.setAccessible(true);
Map<String, Typeface> fontMap = (Map<String, Typeface>) f.get(typeface);
fonts.addAll(fontMap.keySet());
} catch (Exception exception) {
Logger.e(TAG,"Couldn't load fonts from Typeface", exception);
MapStrictMode.strictModeViolation("Couldn't load fonts from Typeface", exception);
}
return fonts;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ public void testCrossSourceCollisions() {
@Test
public void testLocalIdeographFontFamily_enabledByDefault() {
MapboxMapOptions options = MapboxMapOptions.createFromAttributes(RuntimeEnvironment.application, null);
assertEquals("sans-serif", options.getLocalIdeographFontFamily());
assertEquals(MapboxConstants.DEFAULT_FONT, options.getLocalIdeographFontFamily());
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.mapbox.mapboxsdk.utils;

import android.support.test.runner.AndroidJUnit4;

import com.mapbox.mapboxsdk.constants.MapboxConstants;

import org.junit.Test;
import org.junit.runner.RunWith;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;

@RunWith(AndroidJUnit4.class)
public class FontUtilsTest {

@Test
public void testExtractedFontShouldMatchDefault() {
String[] fonts = new String[] {"foo", "bar"};
String actual = FontUtils.extractValidFont(fonts);
assertEquals("Selected font should match", MapboxConstants.DEFAULT_FONT, actual);
}

@Test
public void testExtractedFontShouldMatchMonospace() {
String expected = "monospace";
String[] fonts = new String[] {"foo", expected};
String actual = FontUtils.extractValidFont(fonts);
assertEquals("Selected font should match", expected, actual);
}

@Test
public void testExtractedFontArrayShouldBeNull() {
String[] fonts = null;
String actual = FontUtils.extractValidFont(fonts);
assertNull(actual);
}

@Test
public void testExtractedFontShouldBeNull() {
String actual = FontUtils.extractValidFont(null);
assertNull(actual);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import android.widget.ImageView;

import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
Expand Down Expand Up @@ -68,7 +69,7 @@ private void startSnapShot(final int row, final int column) {

// Optionally the style
.withStyle((column + row) % 2 == 0 ? Style.MAPBOX_STREETS : Style.DARK)
.withLocalIdeographFontFamily("sans-serif");
.withLocalIdeographFontFamily(MapboxConstants.DEFAULT_FONT);

// Optionally the visible region
if (row % 2 == 0) {
Expand Down