Merge "Fixed the waitForLoader method." into honeycomb
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index 0c78952..26b43cd 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -20,6 +20,7 @@
 import com.android.layoutlib.bridge.impl.DelegateManager;
 import com.android.layoutlib.bridge.impl.GcSnapshot;
 
+import android.graphics.Bitmap.Config;
 import android.graphics.Paint_Delegate.FontInfo;
 import android.text.TextUtils;
 
@@ -98,8 +99,13 @@
     // ---- native methods ----
 
     /*package*/ static boolean isOpaque(Canvas thisCanvas) {
-        // FIXME
-        throw new UnsupportedOperationException();
+        // get the delegate from the native int.
+        Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
+        if (canvasDelegate == null) {
+            return false;
+        }
+
+        return canvasDelegate.mBitmap.getConfig() == Config.RGB_565;
     }
 
     /*package*/ static int getWidth(Canvas thisCanvas) {
@@ -511,8 +517,19 @@
     }
 
     /*package*/ static void native_getCTM(int canvas, int matrix) {
-        // FIXME
-        throw new UnsupportedOperationException();
+        // get the delegate from the native int.
+        Canvas_Delegate canvasDelegate = sManager.getDelegate(canvas);
+        if (canvasDelegate == null) {
+            return;
+        }
+
+        Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(matrix);
+        if (matrixDelegate == null) {
+            return;
+        }
+
+        AffineTransform transform = canvasDelegate.getSnapshot().getTransform();
+        matrixDelegate.set(Matrix_Delegate.makeValues(transform));
     }
 
     /*package*/ static boolean native_quickReject(int nativeCanvas,
diff --git a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
index 22c216d..c1f34dc 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
@@ -84,6 +84,14 @@
     }
 
     /**
+     * Sets the content of the matrix with the content of another matrix represented as an array
+     * of values.
+     */
+    public void set(float[] values) {
+        System.arraycopy(values, 0, mValues, 0, MATRIX_SIZE);
+    }
+
+    /**
      * Resets the matrix to be the identity matrix.
      */
     public void reset() {
@@ -105,7 +113,7 @@
         return true;
     }
 
-    public static Matrix_Delegate make(AffineTransform matrix) {
+    public static float[] makeValues(AffineTransform matrix) {
         float[] values = new float[MATRIX_SIZE];
         values[0] = (float) matrix.getScaleX();
         values[1] = (float) matrix.getShearX();
@@ -117,7 +125,11 @@
         values[7] = 0.f;
         values[8] = 1.f;
 
-        return new Matrix_Delegate(values);
+        return values;
+    }
+
+    public static Matrix_Delegate make(AffineTransform matrix) {
+        return new Matrix_Delegate(makeValues(matrix));
     }
 
     public boolean mapRect(RectF dst, RectF src) {
diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
index 9d4970f..43cf91a 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
@@ -375,7 +375,7 @@
     /*package*/ static void nSetShadowLayer(Paint thisPaint, float radius, float dx, float dy,
             int color) {
         // FIXME
-        throw new UnsupportedOperationException();
+        Bridge.getLog().fidelityWarning(null, "Paint.setShadowLayer is not supported.", null);
     }
 
     /*package*/ static float getTextSize(Paint thisPaint) {
diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
index 03a1815..8a50b34 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
@@ -237,8 +237,7 @@
         pathDelegate.quadTo(x1, y1, x2, y2);
     }
 
-    /*package*/ static void native_rQuadTo(int nPath, float dx1, float dy1,
-                                              float dx2, float dy2) {
+    /*package*/ static void native_rQuadTo(int nPath, float dx1, float dy1, float dx2, float dy2) {
         Path_Delegate pathDelegate = sManager.getDelegate(nPath);
         if (pathDelegate == null) {
             return;
@@ -248,7 +247,7 @@
     }
 
     /*package*/ static void native_cubicTo(int nPath, float x1, float y1,
-                float x2, float y2, float x3, float y3) {
+            float x2, float y2, float x3, float y3) {
         Path_Delegate pathDelegate = sManager.getDelegate(nPath);
         if (pathDelegate == null) {
             return;
@@ -258,7 +257,7 @@
     }
 
     /*package*/ static void native_rCubicTo(int nPath, float x1, float y1,
-                float x2, float y2, float x3, float y3) {
+            float x2, float y2, float x3, float y3) {
         Path_Delegate pathDelegate = sManager.getDelegate(nPath);
         if (pathDelegate == null) {
             return;
@@ -295,8 +294,8 @@
         pathDelegate.addRect(rect.left, rect.top, rect.right, rect.bottom, dir);
     }
 
-    /*package*/ static void native_addRect(int nPath, float left, float top,
-                                            float right, float bottom, int dir) {
+    /*package*/ static void native_addRect(int nPath,
+            float left, float top, float right, float bottom, int dir) {
         Path_Delegate pathDelegate = sManager.getDelegate(nPath);
         if (pathDelegate == null) {
             return;
@@ -310,39 +309,35 @@
         throw new UnsupportedOperationException();
     }
 
-    /*package*/ static void native_addCircle(int nPath, float x, float y,
-                                                float radius, int dir) {
+    /*package*/ static void native_addCircle(int nPath, float x, float y, float radius, int dir) {
         // FIXME
         throw new UnsupportedOperationException();
     }
 
     /*package*/ static void native_addArc(int nPath, RectF oval,
-                                            float startAngle, float sweepAngle) {
+            float startAngle, float sweepAngle) {
         // FIXME
         throw new UnsupportedOperationException();
     }
 
     /*package*/ static void native_addRoundRect(int nPath, RectF rect,
-                                                   float rx, float ry, int dir) {
+            float rx, float ry, int dir) {
         // FIXME
         throw new UnsupportedOperationException();
     }
 
-    /*package*/ static void native_addRoundRect(int nPath, RectF r,
-                                                   float[] radii, int dir) {
+    /*package*/ static void native_addRoundRect(int nPath, RectF r, float[] radii, int dir) {
         // FIXME
         throw new UnsupportedOperationException();
     }
 
-    /*package*/ static void native_addPath(int nPath, int src, float dx,
-                                              float dy) {
+    /*package*/ static void native_addPath(int nPath, int src, float dx, float dy) {
         // FIXME
         throw new UnsupportedOperationException();
     }
 
     /*package*/ static void native_addPath(int nPath, int src) {
-        // FIXME
-        throw new UnsupportedOperationException();
+        native_addPath(nPath, src, 0, 0);
     }
 
     /*package*/ static void native_addPath(int nPath, int src, int matrix) {
@@ -350,8 +345,7 @@
         throw new UnsupportedOperationException();
     }
 
-    /*package*/ static void native_offset(int nPath, float dx, float dy,
-                                             int dst_path) {
+    /*package*/ static void native_offset(int nPath, float dx, float dy, int dst_path) {
         Path_Delegate pathDelegate = sManager.getDelegate(nPath);
         if (pathDelegate == null) {
             return;
diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
index c7362c0..11e1ca7 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
@@ -16,6 +16,7 @@
 
 package android.graphics;
 
+import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.impl.DelegateManager;
 import com.android.layoutlib.bridge.impl.FontLoader;
 
@@ -84,7 +85,6 @@
         return delegate.mFonts;
     }
 
-
     // ---- native methods ----
 
     /*package*/ static synchronized int nativeCreate(String familyName, int style) {
@@ -125,13 +125,13 @@
     }
 
     /*package*/ static synchronized int nativeCreateFromAsset(AssetManager mgr, String path) {
-        // FIXME
-        throw new UnsupportedOperationException("Native delegate needed: Typeface_Delegate.nativeCreateFromAsset");
+        Bridge.getLog().fidelityWarning(null, "Typeface.createFromAsset() is not supported.", null);
+        return 0;
     }
 
     /*package*/ static synchronized int nativeCreateFromFile(String path) {
-        // FIXME
-        throw new UnsupportedOperationException("Native delegate needed: Typeface_Delegate.nativeCreateFromFile");
+        Bridge.getLog().fidelityWarning(null, "Typeface.createFromFile() is not supported.", null);
+        return 0;
     }
 
     /*package*/ static void nativeUnref(int native_instance) {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index 7a95c09..e1bf925 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -32,6 +32,7 @@
 import com.android.tools.layoutlib.create.OverrideMethod;
 
 import android.graphics.Bitmap;
+import android.graphics.Typeface;
 import android.graphics.Typeface_Delegate;
 import android.os.Looper;
 
@@ -283,6 +284,10 @@
     @Override
     public boolean dispose() {
         BridgeAssetManager.clearSystem();
+
+        // dispose of the default typeface.
+        Typeface.sDefaults = null;
+
         return true;
     }
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 19c3891..025a318 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -344,6 +344,7 @@
             info.mHasWindowFocus = true;
             info.mWindowVisibility = View.VISIBLE;
             info.mInTouchMode = false; // this is so that we can display selections.
+            info.mHardwareAccelerated = false;
             mViewRoot.dispatchAttachedToWindow(info, 0);
 
             // get the background drawable
@@ -654,25 +655,25 @@
                     LayoutTransition removeTransition = new LayoutTransition();
                     previousParent.setLayoutTransition(removeTransition);
 
-                    // no fade-out
-                    // FIXME: set a non-null do-nothing Animator.
-                    // setting a null animator doesn't work because the child gets its parent
-                    // set to null too late.
-                    //removeTransition.setAnimator(LayoutTransition.DISAPPEARING, null);
+                    // no fade-out. Because we can't rely on layout transition listeners when
+                    // there is no Animator at all, instead we keep the animator but set its
+                    // duration to 0.
+                    // Note: Cannot user Animation.setDuration() directly. Have to set it
+                    // on the LayoutTransition.
+                    removeTransition.setDuration(LayoutTransition.DISAPPEARING, 0);
 
-                    // now for the new parent, if different
                     if (previousParent != newParentView) {
-                        LayoutTransition addTransition = new LayoutTransition();
-
-                        // no fade-in
-                        // FIXME: set a non-null do-nothing Animator.
-                        // setting a null animator doesn't work because the child gets its parent
-                        // set to null too late.
-                        //addTransition.setAnimator(LayoutTransition.APPEARING, null);
-
-                        newParentView.setLayoutTransition(addTransition);
+                        // different parent, set a Layout transition on the new parent.
+                        newParentView.setLayoutTransition(new LayoutTransition());
                     }
 
+                    // no fade-in. Because we can't rely on layout transition listeners when
+                    // there is no Animator at all, instead we keep the animator but set its
+                    // duration to 0.
+                    // Note: Cannot user Animation.setDuration() directly. Have to set it
+                    // on the LayoutTransition.
+                    newParentView.getLayoutTransition().setDuration(LayoutTransition.APPEARING, 0);
+
                     return moveView(previousParent, newParentView, childView, index, params);
                 }
 
@@ -720,9 +721,20 @@
             // check if there is a transition on the previousParent.
             LayoutTransition transition = previousParent.getLayoutTransition();
             if (transition != null) {
-                // in this case there is an animation. This means we have to listener for the
-                // disappearing animation to be done before we can add the view to the new parent.
-                // TODO: check that if the disappearing animation is null, the removal is done during the removeView call which would simplify the code.
+                // in this case there is an animation. This means we have to wait for the child's
+                // parent reference to be null'ed out so that we can add it to the new parent.
+                // It is technically removed right before the DISAPPEARING animation is done (if
+                // the animation of this type is not null, otherwise it's after which is impossible
+                // to handle).
+                // Because there is no move animation, if the new parent is the same as the old
+                // parent, we need to wait until the CHANGE_DISAPPEARING animation is done before
+                // adding the child or the child will appear in its new location before the
+                // other children have made room for it.
+                // If the parents are different, then we can add the child to its new parent right
+                // after the DISAPPEARING animation is done.
+
+                final int waitForType = newParent == previousParent ?
+                        LayoutTransition.CHANGE_DISAPPEARING : LayoutTransition.DISAPPEARING;
 
                 // add a listener to the transition to be notified of the actual removal.
                 transition.addTransitionListener(new TransitionListener() {
@@ -734,7 +746,7 @@
 
                     public void endTransition(LayoutTransition transition, ViewGroup container,
                             View view, int transitionType) {
-                        if (transitionType == LayoutTransition.DISAPPEARING) {
+                        if (transitionType == waitForType) {
                             // add it to the parentView in the correct location
                             if (params != null) {
                                 newParent.addView(view, index, params);