summaryrefslogtreecommitdiffstats
path: root/tools/layoutlib/bridge/src
diff options
context:
space:
mode:
authorDeepanshu Gupta <deepanshu@google.com>2015-01-27 18:35:46 -0800
committerDeepanshu Gupta <deepanshu@google.com>2015-02-03 19:00:43 -0800
commitd51834bdfad0cd3142ac464ab3a3b0db14f884c3 (patch)
tree974123d628772548cbbdf143eb3476daa3396ac4 /tools/layoutlib/bridge/src
parent6ccb72e685da6769d43545c21182ca44e039da3e (diff)
downloadframeworks_base-d51834bdfad0cd3142ac464ab3a3b0db14f884c3.zip
frameworks_base-d51834bdfad0cd3142ac464ab3a3b0db14f884c3.tar.gz
frameworks_base-d51834bdfad0cd3142ac464ab3a3b0db14f884c3.tar.bz2
Add Asset management support for fonts.
Change-Id: I10ca67dcffe244667d4ae0bda65dbc1aa6691d50
Diffstat (limited to 'tools/layoutlib/bridge/src')
-rw-r--r--tools/layoutlib/bridge/src/android/content/res/BridgeAssetManager.java15
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java101
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java11
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java19
4 files changed, 126 insertions, 20 deletions
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeAssetManager.java b/tools/layoutlib/bridge/src/android/content/res/BridgeAssetManager.java
index c41a4ee..2691e56 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeAssetManager.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeAssetManager.java
@@ -16,12 +16,13 @@
package android.content.res;
+import com.android.ide.common.rendering.api.AssetRepository;
import com.android.layoutlib.bridge.Bridge;
-import android.content.res.AssetManager;
-
public class BridgeAssetManager extends AssetManager {
+ private AssetRepository mAssetRepository;
+
/**
* This initializes the static field {@link AssetManager#sSystem} which is used
* by methods who get a global asset manager using {@link AssetManager#getSystem()}.
@@ -48,6 +49,14 @@ public class BridgeAssetManager extends AssetManager {
AssetManager.sSystem = null;
}
- private BridgeAssetManager() {
+ public void setAssetRepository(AssetRepository assetRepository) {
+ mAssetRepository = assetRepository;
+ }
+
+ public AssetRepository getAssetRepository() {
+ return mAssetRepository;
+ }
+
+ public BridgeAssetManager() {
}
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
index ab79664..42de4ec 100644
--- a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
@@ -18,21 +18,28 @@ package android.graphics;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
+import com.android.ide.common.rendering.api.AssetRepository;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.content.res.AssetManager;
+import android.content.res.BridgeAssetManager;
import java.awt.Font;
import java.awt.FontFormatException;
import java.io.File;
import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
import java.util.Scanner;
import java.util.Set;
@@ -56,10 +63,28 @@ public class FontFamily_Delegate {
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_ITALIC = "Italic.ttf";
private static final String FN_ALL_FONTS_LIST = "fontsInSdk.txt";
+ private static final String EXTENSION_OTF = ".otf";
+
+ private static final int CACHE_SIZE = 10;
+ // The cache has a drawback that if the font file changed after the font object was created,
+ // we will not update it.
+ private static final Map<String, FontInfo> sCache =
+ new LinkedHashMap<String, FontInfo>(CACHE_SIZE) {
+ @Override
+ protected boolean removeEldestEntry(Entry<String, FontInfo> eldest) {
+ return size() > CACHE_SIZE;
+ }
+
+ @Override
+ public FontInfo put(String key, FontInfo value) {
+ // renew this entry.
+ FontInfo removed = remove(key);
+ super.put(key, value);
+ return removed;
+ }
+ };
/**
* A class associating {@link Font} with its metadata.
@@ -194,7 +219,7 @@ public class FontFamily_Delegate {
try {
return Font.createFont(Font.TRUETYPE_FONT, f);
} catch (Exception e) {
- if (path.endsWith(".otf") && e instanceof FontFormatException) {
+ if (path.endsWith(EXTENSION_OTF) && e instanceof FontFormatException) {
// If we aren't able to load an Open Type font, don't log a warning just yet.
// We wait for a case where font is being used. Only then we try to log the
// warning.
@@ -281,8 +306,74 @@ public class FontFamily_Delegate {
@LayoutlibDelegate
/*package*/ static boolean nAddFontFromAsset(long nativeFamily, AssetManager mgr, String path) {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Typeface.createFromAsset is not supported.", null, null);
+ FontFamily_Delegate ffd = sManager.getDelegate(nativeFamily);
+ ffd.mValid = true;
+ if (mgr == null) {
+ return false;
+ }
+ if (mgr instanceof BridgeAssetManager) {
+ InputStream fontStream = null;
+ try {
+ AssetRepository assetRepository = ((BridgeAssetManager) mgr).getAssetRepository();
+ if (assetRepository == null) {
+ Bridge.getLog().error(LayoutLog.TAG_MISSING_ASSET, "Asset not found: " + path,
+ null);
+ return false;
+ }
+ if (!assetRepository.isSupported()) {
+ // Don't log any warnings on unsupported IDEs.
+ return false;
+ }
+ // Check cache
+ FontInfo fontInfo = sCache.get(path);
+ if (fontInfo != null) {
+ // renew the font's lease.
+ sCache.put(path, fontInfo);
+ ffd.addFont(fontInfo);
+ return true;
+ }
+ fontStream = assetRepository.openAsset(path, AssetManager.ACCESS_STREAMING);
+ if (fontStream == null) {
+ Bridge.getLog().error(LayoutLog.TAG_MISSING_ASSET, "Asset not found: " + path,
+ path);
+ return false;
+ }
+ Font font = Font.createFont(Font.TRUETYPE_FONT, fontStream);
+ fontInfo = new FontInfo();
+ fontInfo.mFont = font;
+ fontInfo.mWeight = font.isBold() ? BOLD_FONT_WEIGHT : DEFAULT_FONT_WEIGHT;
+ fontInfo.mIsItalic = font.isItalic();
+ ffd.addFont(fontInfo);
+ return true;
+ } catch (IOException e) {
+ Bridge.getLog().error(LayoutLog.TAG_MISSING_ASSET, "Unable to load font " + path, e,
+ path);
+ } catch (FontFormatException e) {
+ if (path.endsWith(EXTENSION_OTF)) {
+ // otf fonts are not supported on the user's config (JRE version + OS)
+ Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
+ "OpenType fonts are not supported yet: " + path, null, path);
+ } else {
+ Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+ "Unable to load font " + path, e, path);
+ }
+ } finally {
+ if (fontStream != null) {
+ try {
+ fontStream.close();
+ } catch (IOException ignored) {
+ }
+ }
+ }
+ return false;
+ }
+ // This should never happen. AssetManager is a final class (from user's perspective), and
+ // we've replaced every creation of AssetManager with our implementation. We create an
+ // exception and log it, but continue with rest of the rendering, without loading this font.
+ Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+ "You have found a bug in the rendering library. Please file a bug at b.android.com.",
+ new RuntimeException("Asset Manager is not an instance of BridgeAssetManager"),
+ null);
return false;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 8523f1a..4c30f58 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -17,6 +17,7 @@
package com.android.layoutlib.bridge.android;
import com.android.annotations.Nullable;
+import com.android.ide.common.rendering.api.AssetRepository;
import com.android.ide.common.rendering.api.ILayoutPullParser;
import com.android.ide.common.rendering.api.IProjectCallback;
import com.android.ide.common.rendering.api.LayoutLog;
@@ -47,6 +48,7 @@ import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
+import android.content.res.BridgeAssetManager;
import android.content.res.BridgeResources;
import android.content.res.BridgeTypedArray;
import android.content.res.Configuration;
@@ -101,6 +103,7 @@ public final class BridgeContext extends Context {
* used to populate the mViewKeyMap.
*/
private final HashMap<Object, Object> mViewKeyHelpMap = new HashMap<Object, Object>();
+ private final BridgeAssetManager mAssets;
private Resources mSystemResources;
private final Object mProjectKey;
private final DisplayMetrics mMetrics;
@@ -140,6 +143,7 @@ public final class BridgeContext extends Context {
*/
public BridgeContext(Object projectKey, DisplayMetrics metrics,
RenderResources renderResources,
+ AssetRepository assets,
IProjectCallback projectCallback,
Configuration config,
int targetSdkVersion,
@@ -150,6 +154,8 @@ public final class BridgeContext extends Context {
mRenderResources = renderResources;
mConfig = config;
+ mAssets = new BridgeAssetManager();
+ mAssets.setAssetRepository(assets);
mApplicationInfo = new ApplicationInfo();
mApplicationInfo.targetSdkVersion = targetSdkVersion;
@@ -1071,9 +1077,8 @@ public final class BridgeContext extends Context {
}
@Override
- public AssetManager getAssets() {
- // pass
- return null;
+ public BridgeAssetManager getAssets() {
+ return mAssets;
}
@Override
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
index 60f5331..127cb72 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
@@ -35,7 +35,6 @@ import com.android.resources.ScreenSize;
import android.content.res.Configuration;
import android.os.HandlerThread_Delegate;
-import android.os.Looper;
import android.util.DisplayMetrics;
import android.view.ViewConfiguration_Accessor;
import android.view.inputmethod.InputMethodManager;
@@ -71,7 +70,7 @@ public abstract class RenderAction<T extends RenderParams> extends FrameworkReso
/**
* Creates a renderAction.
* <p>
- * This <b>must</b> be followed by a call to {@link RenderAction#init()}, which act as a
+ * This <b>must</b> be followed by a call to {@link RenderAction#init(long)}, which act as a
* call to {@link RenderAction#acquire(long)}
*
* @param params the RenderParams. This must be a copy that the action can keep
@@ -121,8 +120,8 @@ public abstract class RenderAction<T extends RenderParams> extends FrameworkReso
// build the context
mContext = new BridgeContext(mParams.getProjectKey(), metrics, resources,
- mParams.getProjectCallback(), getConfiguration(), mParams.getTargetSdkVersion(),
- mParams.isRtlSupported());
+ mParams.getAssets(), mParams.getProjectCallback(), getConfiguration(),
+ mParams.getTargetSdkVersion(), mParams.isRtlSupported());
setUp();
@@ -139,7 +138,7 @@ public abstract class RenderAction<T extends RenderParams> extends FrameworkReso
* The preparation can fail if another rendering took too long and the timeout was elapsed.
*
* More than one call to this from the same thread will have no effect and will return
- * {@link Result#SUCCESS}.
+ * {@link Result.Status#SUCCESS}.
*
* After scene actions have taken place, only one call to {@link #release()} must be
* done.
@@ -173,7 +172,7 @@ public abstract class RenderAction<T extends RenderParams> extends FrameworkReso
* Acquire the lock so that the scene can be acted upon.
* <p>
* This returns null if the lock was just acquired, otherwise it returns
- * {@link Result#SUCCESS} if the lock already belonged to that thread, or another
+ * {@link Result.Status#SUCCESS} if the lock already belonged to that thread, or another
* instance (see {@link Result#getStatus()}) if an error occurred.
*
* @param timeout the time to wait if another rendering is happening.
@@ -184,11 +183,11 @@ public abstract class RenderAction<T extends RenderParams> extends FrameworkReso
*/
private Result acquireLock(long timeout) {
ReentrantLock lock = Bridge.getLock();
- if (lock.isHeldByCurrentThread() == false) {
+ if (!lock.isHeldByCurrentThread()) {
try {
boolean acquired = lock.tryLock(timeout, TimeUnit.MILLISECONDS);
- if (acquired == false) {
+ if (!acquired) {
return ERROR_TIMEOUT.createResult();
}
} catch (InterruptedException e) {
@@ -308,7 +307,7 @@ public abstract class RenderAction<T extends RenderParams> extends FrameworkReso
*/
protected void checkLock() {
ReentrantLock lock = Bridge.getLock();
- if (lock.isHeldByCurrentThread() == false) {
+ if (!lock.isHeldByCurrentThread()) {
throw new IllegalStateException("scene must be acquired first. see #acquire(long)");
}
if (sCurrentContext != mContext) {
@@ -347,6 +346,7 @@ public abstract class RenderAction<T extends RenderParams> extends FrameworkReso
config.screenWidthDp = hardwareConfig.getScreenWidth() / density.getDpiValue();
config.screenHeightDp = hardwareConfig.getScreenHeight() / density.getDpiValue();
if (config.screenHeightDp < config.screenWidthDp) {
+ //noinspection SuspiciousNameCombination
config.smallestScreenWidthDp = config.screenHeightDp;
} else {
config.smallestScreenWidthDp = config.screenWidthDp;
@@ -367,6 +367,7 @@ public abstract class RenderAction<T extends RenderParams> extends FrameworkReso
config.orientation = Configuration.ORIENTATION_LANDSCAPE;
break;
case SQUARE:
+ //noinspection deprecation
config.orientation = Configuration.ORIENTATION_SQUARE;
break;
}