summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDeepanshu Gupta <deepanshu@google.com>2014-08-27 19:30:32 -0700
committerDeepanshu Gupta <deepanshu@google.com>2014-09-10 17:01:16 -0700
commit145bc2d067faa3fb49b71e9e8c8c70b40564061a (patch)
tree32b9f455ed887f9ebabe4073a48996c7d17de226
parent592b95901ef3fa7248bb9b79d8ea9ce3df9628bc (diff)
downloadframeworks_base-145bc2d067faa3fb49b71e9e8c8c70b40564061a.zip
frameworks_base-145bc2d067faa3fb49b71e9e8c8c70b40564061a.tar.gz
frameworks_base-145bc2d067faa3fb49b71e9e8c8c70b40564061a.tar.bz2
LayoutLib: support font weights.
Also fixes a shader delegate method. Change-Id: I86be80ab55d04760084d5bf39235f2ee4de7be23
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java181
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java9
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java36
3 files changed, 166 insertions, 60 deletions
diff --git a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
index bd80cb8..bef5181 100644
--- a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
@@ -16,6 +16,8 @@
package android.graphics;
+import com.android.annotations.NonNull;
+import com.android.annotations.Nullable;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.impl.DelegateManager;
@@ -50,10 +52,12 @@ import static android.graphics.Typeface_Delegate.SYSTEM_FONTS;
*/
public class FontFamily_Delegate {
+ public static final int DEFAULT_FONT_WEIGHT = 400;
+ public static final int BOLD_FONT_WEIGHT_DELTA = 300;
+ public static final int BOLD_FONT_WEIGHT = 700;
+
// FONT_SUFFIX_ITALIC will always match FONT_SUFFIX_BOLDITALIC and hence it must be checked
// separately.
- private static final String FONT_SUFFIX_BOLDITALIC = "BoldItalic.ttf";
- private static final String FONT_SUFFIX_BOLD = "Bold.ttf";
private static final String FONT_SUFFIX_ITALIC = "Italic.ttf";
private static final String FN_ALL_FONTS_LIST = "fontsInSdk.txt";
@@ -61,9 +65,10 @@ public class FontFamily_Delegate {
* A class associating {@link Font} with its metadata.
*/
private static final class FontInfo {
+ @Nullable
Font mFont;
- /** Regular, Bold, Italic, or BoldItalic. */
- int mStyle;
+ int mWeight;
+ boolean mIsItalic;
}
// ---- delegate manager ----
@@ -79,16 +84,18 @@ public class FontFamily_Delegate {
// ---- delegate data ----
private List<FontInfo> mFonts = new ArrayList<FontInfo>();
+
/**
* The variant of the Font Family - compact or elegant.
+ * <p/>
* 0 is unspecified, 1 is compact and 2 is elegant. This needs to be kept in sync with values in
* android.graphics.FontFamily
*
* @see Paint#setElegantTextHeight(boolean)
*/
private FontVariant mVariant;
- // Path of fonts that haven't been created since sFontLoader hasn't been initialized.
- private List<String> mPath = new ArrayList<String>();
+ // List of runnables to process fonts after sFontLoader is initialized.
+ private List<Runnable> mPostInitRunnables = new ArrayList<Runnable>();
/** @see #isValid() */
private boolean mValid = false;
@@ -139,27 +146,30 @@ public class FontFamily_Delegate {
sPostInitDelegate.clear();
}
- public Font getFont(int style) {
- FontInfo plainFont = null;
+ @Nullable
+ public Font getFont(int desiredWeight, boolean isItalic) {
+ FontInfo desiredStyle = new FontInfo();
+ desiredStyle.mWeight = desiredWeight;
+ desiredStyle.mIsItalic = isItalic;
+ FontInfo bestFont = null;
+ int bestMatch = Integer.MAX_VALUE;
for (FontInfo font : mFonts) {
- if (font.mStyle == style) {
- return font.mFont;
- }
- if (font.mStyle == Font.PLAIN && plainFont == null) {
- plainFont = font;
+ int match = computeMatch(font, desiredStyle);
+ if (match < bestMatch) {
+ bestMatch = match;
+ bestFont = font;
}
}
-
- // No font with the mentioned style is found. Try to derive one.
- if (plainFont != null && style > 0 && style < 4) {
- FontInfo styledFont = new FontInfo();
- styledFont.mFont = plainFont.mFont.deriveFont(style);
- styledFont.mStyle = style;
- // Add the font to the list of fonts so that we don't have to derive it the next time.
- mFonts.add(styledFont);
- return styledFont.mFont;
+ if (bestFont == null) {
+ return null;
}
- return null;
+ if (bestMatch == 0) {
+ return bestFont.mFont;
+ }
+ // Derive the font as required and add it to the list of Fonts.
+ deriveFont(bestFont, desiredStyle);
+ addFont(desiredStyle);
+ return desiredStyle.mFont;
}
public FontVariant getVariant() {
@@ -168,27 +178,14 @@ public class FontFamily_Delegate {
/**
* Returns if the FontFamily should contain any fonts. If this returns true and
- * {@link #getFont(int)} returns an empty list, it means that an error occurred while loading
- * the fonts. However, some fonts are deliberately skipped, for example they are not bundled
- * with the SDK. In such a case, this method returns false.
+ * {@link #getFont(int, boolean)} returns an empty list, it means that an error occurred while
+ * loading the fonts. However, some fonts are deliberately skipped, for example they are not
+ * bundled with the SDK. In such a case, this method returns false.
*/
public boolean isValid() {
return mValid;
}
- /*package*/ static int getFontStyle(String path) {
- int style = Font.PLAIN;
- String fontName = path.substring(path.lastIndexOf('/'));
- if (fontName.endsWith(FONT_SUFFIX_BOLDITALIC)) {
- style = Font.BOLD | Font.ITALIC;
- } else if (fontName.endsWith(FONT_SUFFIX_BOLD)) {
- style = Font.BOLD;
- } else if (fontName.endsWith(FONT_SUFFIX_ITALIC)) {
- style = Font.ITALIC;
- }
- return style;
- }
-
/*package*/ static Font loadFont(String path) {
if (path.startsWith(SYSTEM_FONTS) ) {
String relativePath = path.substring(SYSTEM_FONTS.length());
@@ -242,11 +239,16 @@ public class FontFamily_Delegate {
}
@LayoutlibDelegate
- /*package*/ static boolean nAddFont(long nativeFamily, String path) {
- FontFamily_Delegate delegate = getDelegate(nativeFamily);
+ /*package*/ static boolean nAddFont(long nativeFamily, final String path) {
+ final FontFamily_Delegate delegate = getDelegate(nativeFamily);
if (delegate != null) {
if (sFontLocation == null) {
- delegate.mPath.add(path);
+ delegate.mPostInitRunnables.add(new Runnable() {
+ @Override
+ public void run() {
+ delegate.addFont(path);
+ }
+ });
return true;
}
return delegate.addFont(path);
@@ -255,6 +257,25 @@ public class FontFamily_Delegate {
}
@LayoutlibDelegate
+ /*package*/ static boolean nAddFontWeightStyle(long nativeFamily, final String path,
+ final int weight, final boolean isItalic) {
+ final FontFamily_Delegate delegate = getDelegate(nativeFamily);
+ if (delegate != null) {
+ if (sFontLocation == null) {
+ delegate.mPostInitRunnables.add(new Runnable() {
+ @Override
+ public void run() {
+ delegate.addFont(path, weight, isItalic);
+ }
+ });
+ return true;
+ }
+ return delegate.addFont(path, weight, isItalic);
+ }
+ return false;
+ }
+
+ @LayoutlibDelegate
/*package*/ static boolean nAddFontFromAsset(long nativeFamily, AssetManager mgr, String path) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"FontFamily.addFontFromAsset is not supported.", null, null);
@@ -265,15 +286,17 @@ public class FontFamily_Delegate {
// ---- private helper methods ----
private void init() {
- for (String path : mPath) {
- addFont(path);
+ for (Runnable postInitRunnable : mPostInitRunnables) {
+ postInitRunnable.run();
}
- mPath = null;
+ mPostInitRunnables = null;
}
- private boolean addFont(String path) {
- // If the font is not in the list of fonts bundled with the SDK, don't try to load it and
- // mark the FontFamily to be not valid.
+ private boolean addFont(@NonNull String path) {
+ return addFont(path, DEFAULT_FONT_WEIGHT, path.endsWith(FONT_SUFFIX_ITALIC));
+ }
+
+ private boolean addFont(@NonNull String path, int weight, boolean isItalic) {
if (path.startsWith(SYSTEM_FONTS) &&
!SDK_FONTS.contains(path.substring(SYSTEM_FONTS.length()))) {
return mValid = false;
@@ -286,9 +309,67 @@ public class FontFamily_Delegate {
}
FontInfo fontInfo = new FontInfo();
fontInfo.mFont = font;
- fontInfo.mStyle = getFontStyle(path);
- // TODO ensure that mFonts doesn't have the font with this style already.
+ fontInfo.mWeight = weight;
+ fontInfo.mIsItalic = isItalic;
+ addFont(fontInfo);
+ return true;
+ }
+
+ private boolean addFont(@NonNull FontInfo fontInfo) {
+ int weight = fontInfo.mWeight;
+ boolean isItalic = fontInfo.mIsItalic;
+ // The list is usually just two fonts big. So iterating over all isn't as bad as it looks.
+ // It's biggest for roboto where the size is 12.
+ for (FontInfo font : mFonts) {
+ if (font.mWeight == weight && font.mIsItalic == isItalic) {
+ return false;
+ }
+ }
mFonts.add(fontInfo);
return true;
}
+
+ /**
+ * Compute matching metric between two styles - 0 is an exact match.
+ */
+ private static int computeMatch(@NonNull FontInfo font1, @NonNull FontInfo font2) {
+ int score = Math.abs(font1.mWeight - font2.mWeight);
+ if (font1.mIsItalic != font2.mIsItalic) {
+ score += 200;
+ }
+ return score;
+ }
+
+ /**
+ * Try to derive a font from {@code srcFont} for the style in {@code outFont}.
+ * <p/>
+ * {@code outFont} is updated to reflect the style of the derived font.
+ * @param srcFont the source font
+ * @param outFont contains the desired font style. Updated to contain the derived font and
+ * its style
+ * @return outFont
+ */
+ @NonNull
+ private FontInfo deriveFont(@NonNull FontInfo srcFont, @NonNull FontInfo outFont) {
+ int desiredWeight = outFont.mWeight;
+ int srcWeight = srcFont.mWeight;
+ Font derivedFont = srcFont.mFont;
+ // Embolden the font if required.
+ if (desiredWeight >= BOLD_FONT_WEIGHT && desiredWeight - srcWeight > BOLD_FONT_WEIGHT_DELTA / 2) {
+ derivedFont = derivedFont.deriveFont(Font.BOLD);
+ srcWeight += BOLD_FONT_WEIGHT_DELTA;
+ }
+ // Italicize the font if required.
+ if (outFont.mIsItalic && !srcFont.mIsItalic) {
+ derivedFont = derivedFont.deriveFont(Font.ITALIC);
+ } else if (outFont.mIsItalic != srcFont.mIsItalic) {
+ // The desired font is plain, but the src font is italics. We can't convert it back. So
+ // we update the value to reflect the true style of the font we're deriving.
+ outFont.mIsItalic = srcFont.mIsItalic;
+ }
+ outFont.mFont = derivedFont;
+ outFont.mWeight = srcWeight;
+ // No need to update mIsItalics, as it's already been handled above.
+ return outFont;
+ }
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
index 832d0a3..14e9960 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
@@ -76,22 +76,19 @@ public abstract class Shader_Delegate {
// ---- native methods ----
@LayoutlibDelegate
- /*package*/ static void nativeDestructor(long native_shader, long native_with_local_matrix) {
- // TODO: check what's native_with_local_matrix
+ /*package*/ static void nativeDestructor(long native_shader) {
sManager.removeJavaReferenceFor(native_shader);
}
@LayoutlibDelegate
- /*package*/ static long nativeSetLocalMatrix(long native_shader,
- long native_with_local_matrix, long matrix_instance) {
+ /*package*/ static void nativeSetLocalMatrix(long native_shader, long matrix_instance) {
// get the delegate from the native int.
Shader_Delegate shaderDelegate = sManager.getDelegate(native_shader);
if (shaderDelegate == null) {
- return 0;
+ return;
}
shaderDelegate.mLocalMatrix = Matrix_Delegate.getDelegate(matrix_instance);
- return 0;
}
// ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
index 72fe61c..276e134 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
@@ -55,8 +55,9 @@ public final class Typeface_Delegate {
@NonNull
private final FontFamily_Delegate[] mFontFamilies; // the reference to FontFamily_Delegate.
- /** @see FontFamily_Delegate.FontInfo#mStyle */
+ /** @see Font#getStyle() */
private final int mStyle;
+ private final int mWeight;
private static long sDefaultTypeface;
@@ -84,11 +85,18 @@ public final class Typeface_Delegate {
@NonNull
public List<Font> getFonts(FontVariant variant) {
assert variant != FontVariant.NONE;
+
+ // Calculate the required weight based on style and weight of this typeface.
+ int weight = mWeight + ((mStyle & Font.BOLD) == 0 ? 0 : FontFamily_Delegate.BOLD_FONT_WEIGHT_DELTA);
+ if (weight > 900) {
+ weight = 900;
+ }
+ final boolean isItalic = (mStyle & Font.ITALIC) != 0;
List<Font> fonts = new ArrayList<Font>(mFontFamilies.length);
for (int i = 0; i < mFontFamilies.length; i++) {
FontFamily_Delegate ffd = mFontFamilies[i];
if (ffd != null && ffd.isValid()) {
- Font font = ffd.getFont(mStyle);
+ Font font = ffd.getFont(weight, isItalic);
if (font != null) {
FontVariant ffdVariant = ffd.getVariant();
if (ffdVariant == FontVariant.NONE) {
@@ -102,7 +110,7 @@ public final class Typeface_Delegate {
FontFamily_Delegate ffd2 = mFontFamilies[++i];
assert ffd2 != null;
FontVariant ffd2Variant = ffd2.getVariant();
- Font font2 = ffd2.getFont(mStyle);
+ Font font2 = ffd2.getFont(weight, isItalic);
assert ffd2Variant != FontVariant.NONE && ffd2Variant != ffdVariant
&& font2 != null;
// Add the font with the matching variant to the list.
@@ -135,7 +143,22 @@ public final class Typeface_Delegate {
return 0;
}
- return sManager.addNewDelegate(new Typeface_Delegate(delegate.mFontFamilies, style));
+ return sManager.addNewDelegate(new Typeface_Delegate(delegate.mFontFamilies, style,
+ delegate.mWeight));
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static long nativeCreateWeightAlias(long native_instance, int weight) {
+ Typeface_Delegate delegate = sManager.getDelegate(native_instance);
+ if (delegate == null) {
+ delegate = sManager.getDelegate(sDefaultTypeface);
+ }
+ if (delegate == null) {
+ return 0;
+ }
+ Typeface_Delegate weightAlias =
+ new Typeface_Delegate(delegate.mFontFamilies, delegate.mStyle, weight);
+ return sManager.addNewDelegate(weightAlias);
}
@LayoutlibDelegate
@@ -176,7 +199,12 @@ public final class Typeface_Delegate {
// ---- Private delegate/helper methods ----
private Typeface_Delegate(@NonNull FontFamily_Delegate[] fontFamilies, int style) {
+ this(fontFamilies, style, FontFamily_Delegate.DEFAULT_FONT_WEIGHT);
+ }
+
+ public Typeface_Delegate(@NonNull FontFamily_Delegate[] fontFamilies, int style, int weight) {
mFontFamilies = fontFamilies;
mStyle = style;
+ mWeight = weight;
}
}