Move layoutlib typeface implementation to delegate.

Also move BridgeContentProvider to its own class to make it
less messy in BridgeContentResolver.

Change-Id: Id3462218b500d43d4c9b20b25326ad24e4106fa5
diff --git a/bridge/src/android/graphics/Paint.java b/bridge/src/android/graphics/Paint.java
index d13b5fe..2de21c1 100644
--- a/bridge/src/android/graphics/Paint.java
+++ b/bridge/src/android/graphics/Paint.java
@@ -249,7 +249,7 @@
     private void updateFontObject() {
         if (mTypeface != null) {
             // Get the fonts from the TypeFace object.
-            List<Font> fonts = mTypeface.getFonts();
+            List<Font> fonts = Typeface_Delegate.getFonts(mTypeface);
 
             // create new font objects as well as FontMetrics, based on the current text size
             // and skew info.
diff --git a/bridge/src/android/graphics/Typeface.java b/bridge/src/android/graphics/Typeface.java
deleted file mode 100644
index af3adb5..0000000
--- a/bridge/src/android/graphics/Typeface.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.layoutlib.bridge.FontLoader;
-
-import android.content.res.AssetManager;
-
-import java.awt.Font;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Re-implementation of Typeface over java.awt
- */
-public class Typeface {
-    private static final String DEFAULT_FAMILY = "sans-serif";
-    private static final int[] styleBuffer = new int[1];
-
-    /** The default NORMAL typeface object */
-    public static Typeface DEFAULT;
-    /**
-     * The default BOLD typeface object. Note: this may be not actually be
-     * bold, depending on what fonts are installed. Call getStyle() to know
-     * for sure.
-     */
-    public static Typeface DEFAULT_BOLD;
-    /** The NORMAL style of the default sans serif typeface. */
-    public static Typeface SANS_SERIF;
-    /** The NORMAL style of the default serif typeface. */
-    public static Typeface SERIF;
-    /** The NORMAL style of the default monospace typeface. */
-    public static Typeface MONOSPACE;
-
-    private static Typeface[] sDefaults;
-    private static FontLoader mFontLoader;
-
-    private final int mStyle;
-    private final List<Font> mFonts;
-    private final String mFamily;
-
-    // Style
-    public static final int NORMAL = _Original_Typeface.NORMAL;
-    public static final int BOLD = _Original_Typeface.BOLD;
-    public static final int ITALIC = _Original_Typeface.ITALIC;
-    public static final int BOLD_ITALIC = _Original_Typeface.BOLD_ITALIC;
-
-    /**
-     * Returns the underlying {@link Font} objects. The first item in the list is the real
-     * font. Any other items are fallback fonts for characters not found in the first one.
-     */
-    public List<Font> getFonts() {
-        return mFonts;
-    }
-
-    /** Returns the typeface's intrinsic style attributes */
-    public int getStyle() {
-        return mStyle;
-    }
-
-    /** Returns true if getStyle() has the BOLD bit set. */
-    public final boolean isBold() {
-        return (getStyle() & BOLD) != 0;
-    }
-
-    /** Returns true if getStyle() has the ITALIC bit set. */
-    public final boolean isItalic() {
-        return (getStyle() & ITALIC) != 0;
-    }
-
-    /**
-     * Create a typeface object given a family name, and option style information.
-     * If null is passed for the name, then the "default" font will be chosen.
-     * The resulting typeface object can be queried (getStyle()) to discover what
-     * its "real" style characteristics are.
-     *
-     * @param familyName May be null. The name of the font family.
-     * @param style  The style (normal, bold, italic) of the typeface.
-     *               e.g. NORMAL, BOLD, ITALIC, BOLD_ITALIC
-     * @return The best matching typeface.
-     */
-    public static Typeface create(String familyName, int style) {
-        styleBuffer[0] = style;
-        Font font = mFontLoader.getFont(familyName, styleBuffer);
-        if (font != null) {
-            ArrayList<Font> list = new ArrayList<Font>();
-            list.add(font);
-            list.addAll(mFontLoader.getFallBackFonts());
-            return new Typeface(familyName, styleBuffer[0], list);
-        }
-
-        return null;
-    }
-
-    /**
-     * Create a typeface object that best matches the specified existing
-     * typeface and the specified Style. Use this call if you want to pick a new
-     * style from the same family of an existing typeface object. If family is
-     * null, this selects from the default font's family.
-     *
-     * @param family May be null. The name of the existing type face.
-     * @param style  The style (normal, bold, italic) of the typeface.
-     *               e.g. NORMAL, BOLD, ITALIC, BOLD_ITALIC
-     * @return The best matching typeface.
-     */
-    public static Typeface create(Typeface family, int style) {
-        styleBuffer[0] = style;
-        Font font = mFontLoader.getFont(family.mFamily, styleBuffer);
-        if (font != null) {
-            ArrayList<Font> list = new ArrayList<Font>();
-            list.add(font);
-            list.addAll(mFontLoader.getFallBackFonts());
-            return new Typeface(family.mFamily, styleBuffer[0], list);
-        }
-
-        return null;
-    }
-
-    /**
-     * Returns one of the default typeface objects, based on the specified style
-     *
-     * @return the default typeface that corresponds to the style
-     */
-    public static Typeface defaultFromStyle(int style) {
-        return sDefaults[style];
-    }
-
-    /**
-     * Create a new typeface from the specified font data.
-     * @param mgr The application's asset manager
-     * @param path  The file name of the font data in the assets directory
-     * @return The new typeface.
-     */
-    public static Typeface createFromAsset(AssetManager mgr, String path) {
-        return null;
-        //return new Typeface(nativeCreateFromAsset(mgr, path));
-    }
-
-    // don't allow clients to call this directly
-    private Typeface(String family, int style, List<Font> fonts) {
-        mFamily = family;
-        mFonts = Collections.unmodifiableList(fonts);
-        mStyle = style;
-    }
-
-    public static void init(FontLoader fontLoader) {
-        mFontLoader = fontLoader;
-
-        DEFAULT = create(DEFAULT_FAMILY, NORMAL);
-        DEFAULT_BOLD = create(DEFAULT_FAMILY, BOLD);
-        SANS_SERIF = create("sans-serif", NORMAL);
-        SERIF = create("serif", NORMAL);
-        MONOSPACE = create("monospace", NORMAL);
-        sDefaults = new Typeface[] {
-                DEFAULT,
-                DEFAULT_BOLD,
-                create(DEFAULT_FAMILY, ITALIC),
-                create(DEFAULT_FAMILY, BOLD_ITALIC),
-        };
-
-        /*
-        DEFAULT         = create((String)null, 0);
-        DEFAULT_BOLD    = create((String)null, Typeface.BOLD);
-        SANS_SERIF      = create("sans-serif", 0);
-        SERIF           = create("serif", 0);
-        MONOSPACE       = create("monospace", 0);
-
-        sDefaults = new Typeface[] {
-            DEFAULT,
-            DEFAULT_BOLD,
-            create((String)null, Typeface.ITALIC),
-            create((String)null, Typeface.BOLD_ITALIC),
-        };*/
-    }
-}
diff --git a/bridge/src/android/graphics/Typeface_Delegate.java b/bridge/src/android/graphics/Typeface_Delegate.java
new file mode 100644
index 0000000..309d934
--- /dev/null
+++ b/bridge/src/android/graphics/Typeface_Delegate.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.FontLoader;
+
+import android.content.res.AssetManager;
+
+import java.awt.Font;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Delegate implementing the native methods of android.graphics.Typeface
+ *
+ * Through the layoutlib_create tool, the original native methods of Typeface have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original Matrix class.
+ *
+ * @see DelegateManager
+ *
+ */
+public final class Typeface_Delegate {
+
+    // ---- delegate manager ----
+    private static final DelegateManager<Typeface_Delegate> sManager =
+            new DelegateManager<Typeface_Delegate>();
+
+    // ---- delegate helper data ----
+    private static final String DEFAULT_FAMILY = "sans-serif";
+    private static final int[] STYLE_BUFFER = new int[1];
+
+    private static FontLoader sFontLoader;
+    private static final List<Typeface_Delegate> sPostInitDelegate =
+            new ArrayList<Typeface_Delegate>();
+
+    // ---- delegate data ----
+
+    private final String mFamily;
+    private int mStyle;
+    private List<Font> mFonts;
+
+
+    // ---- Public Helper methods ----
+
+    public static synchronized void init(FontLoader fontLoader) {
+        sFontLoader = fontLoader;
+
+        for (Typeface_Delegate delegate : sPostInitDelegate) {
+            delegate.init();
+        }
+        sPostInitDelegate.clear();
+    }
+
+    public static List<Font> getFonts(Typeface typeface) {
+        Typeface_Delegate delegate = sManager.getDelegate(typeface.native_instance);
+        if (delegate == null) {
+            assert false;
+            return null;
+        }
+
+        return delegate.mFonts;
+    }
+
+
+    // ---- native methods ----
+
+    public static synchronized int nativeCreate(String familyName, int style) {
+        if (familyName == null) {
+            familyName = DEFAULT_FAMILY;
+        }
+
+        Typeface_Delegate newDelegate = new Typeface_Delegate(familyName, style);
+        if (sFontLoader != null) {
+            newDelegate.init();
+        } else {
+            // font loader has not been initialized yet, add the delegate to a list of delegates
+            // to init when the font loader is initialized.
+            // There won't be any rendering before this happens anyway.
+            sPostInitDelegate.add(newDelegate);
+        }
+
+        return sManager.addDelegate(newDelegate);
+    }
+
+    public static synchronized int nativeCreateFromTypeface(int native_instance, int style) {
+        Typeface_Delegate delegate = sManager.getDelegate(native_instance);
+        if (delegate == null) {
+            assert false;
+            return 0;
+        }
+
+        Typeface_Delegate newDelegate = new Typeface_Delegate(delegate.mFamily, style);
+        if (sFontLoader != null) {
+            newDelegate.init();
+        } else {
+            // font loader has not been initialized yet, add the delegate to a list of delegates
+            // to init when the font loader is initialized.
+            // There won't be any rendering before this happens anyway.
+            sPostInitDelegate.add(newDelegate);
+        }
+
+        return sManager.addDelegate(newDelegate);
+    }
+
+    public static synchronized int nativeCreateFromAsset(AssetManager mgr, String path) {
+        // FIXME
+        throw new UnsupportedOperationException();
+    }
+
+    public static synchronized int nativeCreateFromFile(String path) {
+        // FIXME
+        throw new UnsupportedOperationException();
+    }
+
+    public static void nativeUnref(int native_instance) {
+        sManager.removeDelegate(native_instance);
+    }
+
+    public static int nativeGetStyle(int native_instance) {
+        Typeface_Delegate delegate = sManager.getDelegate(native_instance);
+        if (delegate == null) {
+            assert false;
+            return 0;
+        }
+
+        return delegate.mStyle;
+    }
+
+    public static void setGammaForText(float blackGamma, float whiteGamma) {
+        // This is for device testing only: pass
+    }
+
+    // ---- Private delegate/helper methods ----
+
+    private Typeface_Delegate(String family, int style) {
+        mFamily = family;
+        mStyle = style;
+    }
+
+    private void init() {
+        STYLE_BUFFER[0] = mStyle;
+        Font font = sFontLoader.getFont(mFamily, STYLE_BUFFER);
+        if (font != null) {
+            List<Font> list = new ArrayList<Font>();
+            list.add(font);
+            list.addAll(sFontLoader.getFallBackFonts());
+            mFonts = Collections.unmodifiableList(list);
+            mStyle = STYLE_BUFFER[0];
+        }
+    }
+}
diff --git a/bridge/src/com/android/layoutlib/bridge/Bridge.java b/bridge/src/com/android/layoutlib/bridge/Bridge.java
index eb0eba2..9eb83c8 100644
--- a/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -31,13 +31,12 @@
 import com.android.tools.layoutlib.create.OverrideMethod;
 
 import android.content.ClipData;
-import android.content.ClipDescription;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.graphics.Region;
-import android.graphics.Typeface;
+import android.graphics.Typeface_Delegate;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.Handler;
@@ -49,9 +48,9 @@
 import android.util.TypedValue;
 import android.view.BridgeInflater;
 import android.view.DragEvent;
-import android.view.InputChannel;
 import android.view.IWindow;
 import android.view.IWindowSession;
+import android.view.InputChannel;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.Surface;
@@ -220,7 +219,7 @@
         // load the fonts.
         FontLoader fontLoader = FontLoader.create(fontOsLocation);
         if (fontLoader != null) {
-            Typeface.init(fontLoader);
+            Typeface_Delegate.init(fontLoader);
         } else {
             return false;
         }
@@ -1007,7 +1006,7 @@
             // pass for now.
             return 0;
         }
-        
+
         @SuppressWarnings("unused")
         public void finishDrawing(IWindow arg0) throws RemoteException {
             // pass for now.
diff --git a/bridge/src/com/android/layoutlib/bridge/BridgeContentProvider.java b/bridge/src/com/android/layoutlib/bridge/BridgeContentProvider.java
new file mode 100644
index 0000000..9d6dd27
--- /dev/null
+++ b/bridge/src/com/android/layoutlib/bridge/BridgeContentProvider.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.bridge;
+
+import android.content.ContentProviderOperation;
+import android.content.ContentProviderResult;
+import android.content.ContentValues;
+import android.content.IContentProvider;
+import android.content.OperationApplicationException;
+import android.content.res.AssetFileDescriptor;
+import android.database.Cursor;
+import android.database.CursorWindow;
+import android.database.IBulkCursor;
+import android.database.IContentObserver;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+
+/**
+ * Mock implementation of {@link IContentProvider}.
+ *
+ * TODO: never return null when the method is not supposed to. Return fake data instead.
+ */
+public final class BridgeContentProvider implements IContentProvider {
+
+    public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> arg0)
+            throws RemoteException, OperationApplicationException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public int bulkInsert(Uri arg0, ContentValues[] arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    public IBulkCursor bulkQuery(Uri arg0, String[] arg1, String arg2, String[] arg3,
+            String arg4, IContentObserver arg5, CursorWindow arg6) throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Bundle call(String arg0, String arg1, Bundle arg2) throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public int delete(Uri arg0, String arg1, String[] arg2) throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    public String getType(Uri arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Uri insert(Uri arg0, ContentValues arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public AssetFileDescriptor openAssetFile(Uri arg0, String arg1) throws RemoteException,
+            FileNotFoundException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public ParcelFileDescriptor openFile(Uri arg0, String arg1) throws RemoteException,
+            FileNotFoundException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Cursor query(Uri arg0, String[] arg1, String arg2, String[] arg3, String arg4)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    public IBinder asBinder() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public String[] getStreamTypes(Uri arg0, String arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public AssetFileDescriptor openTypedAssetFile(Uri arg0, String arg1, Bundle arg2)
+            throws RemoteException, FileNotFoundException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+}
diff --git a/bridge/src/com/android/layoutlib/bridge/BridgeContentResolver.java b/bridge/src/com/android/layoutlib/bridge/BridgeContentResolver.java
index a063455..e15cb69 100644
--- a/bridge/src/com/android/layoutlib/bridge/BridgeContentResolver.java
+++ b/bridge/src/com/android/layoutlib/bridge/BridgeContentResolver.java
@@ -16,27 +16,12 @@
 
 package com.android.layoutlib.bridge;
 
-import android.content.ContentProviderOperation;
-import android.content.ContentProviderResult;
 import android.content.ContentResolver;
-import android.content.ContentValues;
 import android.content.Context;
 import android.content.IContentProvider;
-import android.content.OperationApplicationException;
-import android.content.res.AssetFileDescriptor;
 import android.database.ContentObserver;
-import android.database.Cursor;
-import android.database.CursorWindow;
-import android.database.IBulkCursor;
-import android.database.IContentObserver;
 import android.net.Uri;
 import android.os.Bundle;
-import android.os.IBinder;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-
-import java.io.FileNotFoundException;
-import java.util.ArrayList;
 
 /**
  * A mock content resolver for the LayoutLib Bridge.
@@ -49,87 +34,6 @@
 
     private BridgeContentProvider mProvider = null;
 
-    public static final class BridgeContentProvider implements IContentProvider {
-
-        public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> arg0)
-                throws RemoteException, OperationApplicationException {
-            // TODO Auto-generated method stub
-            return null;
-        }
-
-        public int bulkInsert(Uri arg0, ContentValues[] arg1) throws RemoteException {
-            // TODO Auto-generated method stub
-            return 0;
-        }
-
-        public IBulkCursor bulkQuery(Uri arg0, String[] arg1, String arg2, String[] arg3,
-                String arg4, IContentObserver arg5, CursorWindow arg6) throws RemoteException {
-            // TODO Auto-generated method stub
-            return null;
-        }
-
-        public Bundle call(String arg0, String arg1, Bundle arg2) throws RemoteException {
-            // TODO Auto-generated method stub
-            return null;
-        }
-
-        public int delete(Uri arg0, String arg1, String[] arg2) throws RemoteException {
-            // TODO Auto-generated method stub
-            return 0;
-        }
-
-        public String getType(Uri arg0) throws RemoteException {
-            // TODO Auto-generated method stub
-            return null;
-        }
-
-        public Uri insert(Uri arg0, ContentValues arg1) throws RemoteException {
-            // TODO Auto-generated method stub
-            return null;
-        }
-
-        public AssetFileDescriptor openAssetFile(Uri arg0, String arg1) throws RemoteException,
-                FileNotFoundException {
-            // TODO Auto-generated method stub
-            return null;
-        }
-
-        public ParcelFileDescriptor openFile(Uri arg0, String arg1) throws RemoteException,
-                FileNotFoundException {
-            // TODO Auto-generated method stub
-            return null;
-        }
-
-        public Cursor query(Uri arg0, String[] arg1, String arg2, String[] arg3, String arg4)
-                throws RemoteException {
-            // TODO Auto-generated method stub
-            return null;
-        }
-
-        public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3)
-                throws RemoteException {
-            // TODO Auto-generated method stub
-            return 0;
-        }
-
-        public IBinder asBinder() {
-            // TODO Auto-generated method stub
-            return null;
-        }
-
-        public String[] getStreamTypes(Uri arg0, String arg1) throws RemoteException {
-            // TODO Auto-generated method stub
-            return null;
-        }
-
-        public AssetFileDescriptor openTypedAssetFile(Uri arg0, String arg1, Bundle arg2)
-                throws RemoteException, FileNotFoundException {
-            // TODO Auto-generated method stub
-            return null;
-        }
-
-    }
-
     public BridgeContentResolver(Context context) {
         super(context);
     }
diff --git a/bridge/src/com/android/layoutlib/bridge/FontLoader.java b/bridge/src/com/android/layoutlib/bridge/FontLoader.java
index 801503b..de89a81 100644
--- a/bridge/src/com/android/layoutlib/bridge/FontLoader.java
+++ b/bridge/src/com/android/layoutlib/bridge/FontLoader.java
@@ -134,6 +134,15 @@
         return mFallBackFonts;
     }
 
+    /**
+     * Returns a {@link Font} object given a family name and a style value (constant in
+     * {@link Typeface}).
+     * @param family the family name
+     * @param style a 1-item array containing the requested style. Based on the font being read
+     *              the actual style may be different. The array contains the actual style after
+     *              the method returns.
+     * @return the font object or null if no match could be found.
+     */
     public synchronized Font getFont(String family, int[] style) {
         if (family == null) {
             return null;