More implementation of the layoutlib Paint/Canvas delegates.

Change-Id: I0c0029b9a679af4ae0178488f70b2a90292ea42d
diff --git a/bridge/src/android/graphics/Paint_Delegate.java b/bridge/src/android/graphics/Paint_Delegate.java
index e8079ed..f2602b5 100644
--- a/bridge/src/android/graphics/Paint_Delegate.java
+++ b/bridge/src/android/graphics/Paint_Delegate.java
@@ -20,7 +20,9 @@
 
 import android.graphics.Paint.FontMetrics;
 import android.graphics.Paint.FontMetricsInt;
+import android.text.TextUtils;
 
+import java.awt.BasicStroke;
 import java.awt.Font;
 import java.awt.Toolkit;
 import java.awt.font.FontRenderContext;
@@ -47,7 +49,7 @@
     /**
      * Class associating a {@link Font} and it's {@link java.awt.FontMetrics}.
      */
-    public static final class FontInfo {
+    /*package*/ static final class FontInfo {
         Font mFont;
         java.awt.FontMetrics mMetrics;
     }
@@ -67,7 +69,7 @@
     private int mStyle;
     private int mCap;
     private int mJoin;
-    private int mAlign;
+    private int mTextAlign;
     private int mTypeface;
     private float mStrokeWidth;
     private float mStrokeMiter;
@@ -78,6 +80,10 @@
 
     // ---- Public Helper methods ----
 
+    public static Paint_Delegate getDelegate(int native_paint) {
+        return sManager.getDelegate(native_paint);
+    }
+
     /**
      * Returns the list of {@link Font} objects. The first item is the main font, the rest
      * are fall backs for characters not present in the main font.
@@ -86,6 +92,57 @@
         return mFonts;
     }
 
+    public boolean isFilterBitmap() {
+        return (mFlags & Paint.FILTER_BITMAP_FLAG) != 0;
+    }
+
+    public int getStyle() {
+        return mStyle;
+    }
+
+    public int getColor() {
+        return mColor;
+    }
+
+    public int getAlpha() {
+        return mColor >>> 24;
+    }
+
+    public int getTextAlign() {
+        return mTextAlign;
+    }
+
+    public float getStrokeWidth() {
+        return mStrokeWidth;
+    }
+
+    public float getStrokeMiter() {
+        return mStrokeMiter;
+    }
+
+    public int getJavaCap() {
+        switch (Paint.sCapArray[mCap]) {
+            case BUTT:
+                return BasicStroke.CAP_BUTT;
+            case ROUND:
+                return BasicStroke.CAP_ROUND;
+            default:
+            case SQUARE:
+                return BasicStroke.CAP_SQUARE;
+        }
+    }
+
+    public int getJavaJoin() {
+        switch (Paint.sJoinArray[mJoin]) {
+            default:
+            case MITER:
+                return BasicStroke.JOIN_MITER;
+            case ROUND:
+                return BasicStroke.JOIN_ROUND;
+            case BEVEL:
+                return BasicStroke.JOIN_BEVEL;
+        }
+    }
 
     // ---- native methods ----
 
@@ -112,8 +169,7 @@
     }
 
     /*package*/ static void setFilterBitmap(Paint thisPaint, boolean filter) {
-        // FIXME
-        throw new UnsupportedOperationException();
+        setFlag(thisPaint, Paint.FILTER_BITMAP_FLAG, filter);
     }
 
     /*package*/ static void setAntiAlias(Paint thisPaint, boolean aa) {
@@ -174,7 +230,7 @@
             return 0;
         }
 
-        return delegate.mColor >>> 24;
+        return delegate.getAlpha();
     }
 
     /*package*/ static void setAlpha(Paint thisPaint, int a) {
@@ -315,13 +371,53 @@
     }
 
     /*package*/ static float getFontMetrics(Paint thisPaint, FontMetrics metrics) {
-        // FIXME
-        throw new UnsupportedOperationException();
+        // get the delegate
+        Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+        if (delegate == null) {
+            assert false;
+            return 0;
+        }
+
+        if (delegate.mFonts.size() > 0) {
+            java.awt.FontMetrics javaMetrics = delegate.mFonts.get(0).mMetrics;
+            if (metrics != null) {
+                // Android expects negative ascent so we invert the value from Java.
+                metrics.top = - javaMetrics.getMaxAscent();
+                metrics.ascent = - javaMetrics.getAscent();
+                metrics.descent = javaMetrics.getDescent();
+                metrics.bottom = javaMetrics.getMaxDescent();
+                metrics.leading = javaMetrics.getLeading();
+            }
+
+            return javaMetrics.getHeight();
+        }
+
+        return 0;
     }
 
     /*package*/ static int getFontMetricsInt(Paint thisPaint, FontMetricsInt fmi) {
-        // FIXME
-        throw new UnsupportedOperationException();
+        // get the delegate
+        Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+        if (delegate == null) {
+            assert false;
+            return 0;
+        }
+
+        if (delegate.mFonts.size() > 0) {
+            java.awt.FontMetrics javaMetrics = delegate.mFonts.get(0).mMetrics;
+            if (fmi != null) {
+                // Android expects negative ascent so we invert the value from Java.
+                fmi.top = - javaMetrics.getMaxAscent();
+                fmi.ascent = - javaMetrics.getAscent();
+                fmi.descent = javaMetrics.getDescent();
+                fmi.bottom = javaMetrics.getMaxDescent();
+                fmi.leading = javaMetrics.getLeading();
+            }
+
+            return javaMetrics.getHeight();
+        }
+
+        return 0;
     }
 
     /*package*/ static float native_measureText(Paint thisPaint, char[] text, int index,
@@ -336,56 +432,7 @@
             return 0;
         }
 
-        if (delegate.mFonts.size() > 0) {
-            FontInfo mainFont = delegate.mFonts.get(0);
-            int i = index;
-            int lastIndex = index + count;
-            float total = 0f;
-            while (i < lastIndex) {
-                // always start with the main font.
-                int upTo = mainFont.mFont.canDisplayUpTo(text, i, lastIndex);
-                if (upTo == -1) {
-                    // shortcut to exit
-                    return total + mainFont.mMetrics.charsWidth(text, i, lastIndex - i);
-                } else if (upTo > 0) {
-                    total += mainFont.mMetrics.charsWidth(text, i, upTo - i);
-                    i = upTo;
-                    // don't call continue at this point. Since it is certain the main font
-                    // cannot display the font a index upTo (now ==i), we move on to the
-                    // fallback fonts directly.
-                }
-
-                // no char supported, attempt to read the next char(s) with the
-                // fallback font. In this case we only test the first character
-                // and then go back to test with the main font.
-                // Special test for 2-char characters.
-                boolean foundFont = false;
-                for (int f = 1 ; f < delegate.mFonts.size() ; f++) {
-                    FontInfo fontInfo = delegate.mFonts.get(f);
-
-                    // need to check that the font can display the character. We test
-                    // differently if the char is a high surrogate.
-                    int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1;
-                    upTo = fontInfo.mFont.canDisplayUpTo(text, i, i + charCount);
-                    if (upTo == -1) {
-                        total += fontInfo.mMetrics.charsWidth(text, i, charCount);
-                        i += charCount;
-                        foundFont = true;
-                        break;
-
-                    }
-                }
-
-                // in case no font can display the char, measure it with the main font.
-                if (foundFont == false) {
-                    int size = Character.isHighSurrogate(text[i]) ? 2 : 1;
-                    total += mainFont.mMetrics.charsWidth(text, i, size);
-                    i += size;
-                }
-            }
-        }
-
-        return 0;
+        return delegate.measureText(text, index, count);
     }
 
     /*package*/ static float native_measureText(Paint thisPaint, String text, int start, int end) {
@@ -576,7 +623,7 @@
             return 0;
         }
 
-        return delegate.mAlign;
+        return delegate.mTextAlign;
     }
 
     /*package*/ static void native_setTextAlign(int native_object, int align) {
@@ -587,7 +634,7 @@
             return;
         }
 
-        delegate.mAlign = align;
+        delegate.mTextAlign = align;
     }
 
     /*package*/ static float native_getFontMetrics(int native_paint, FontMetrics metrics) {
@@ -610,15 +657,58 @@
     /*package*/ static float native_getTextRunAdvances(int native_object,
             char[] text, int index, int count, int contextIndex, int contextCount,
             int flags, float[] advances, int advancesIndex) {
-        // FIXME
-        throw new UnsupportedOperationException();
+        // get the delegate from the native int.
+        Paint_Delegate delegate = sManager.getDelegate(native_object);
+        if (delegate == null) {
+            assert false;
+            return 0.f;
+        }
+
+        if (delegate.mFonts.size() > 0) {
+            // FIXME: handle multi-char characters.
+            // see measureText.
+            float totalAdvance = 0;
+            for (int i = 0; i < count; i++) {
+                char c = text[i + index];
+                boolean found = false;
+                for (FontInfo info : delegate.mFonts) {
+                    if (info.mFont.canDisplay(c)) {
+                        float adv = info.mMetrics.charWidth(c);
+                        totalAdvance += adv;
+                        if (advances != null) {
+                            advances[i] = adv;
+                        }
+
+                        found = true;
+                        break;
+                    }
+                }
+
+                if (found == false) {
+                    // no advance for this char.
+                    if (advances != null) {
+                        advances[i] = 0.f;
+                    }
+                }
+            }
+
+            return totalAdvance;
+        }
+
+        return 0;
+
     }
 
     /*package*/ static float native_getTextRunAdvances(int native_object,
             String text, int start, int end, int contextStart, int contextEnd,
             int flags, float[] advances, int advancesIndex) {
-        // FIXME
-        throw new UnsupportedOperationException();
+        // FIXME: support contextStart, contextEnd and direction flag
+        int count = end - start;
+        char[] buffer = TemporaryBuffer.obtain(count);
+        TextUtils.getChars(text, start, end, buffer, 0);
+
+        return native_getTextRunAdvances(native_object, buffer, 0, count, contextStart,
+                contextEnd - contextStart, flags, advances, advancesIndex);
     }
 
     /*package*/ static int native_getTextRunCursor(Paint thisPaint, int native_object, char[] text,
@@ -681,7 +771,7 @@
         mStyle = paint.mStyle;
         mCap = paint.mCap;
         mJoin = paint.mJoin;
-        mAlign = paint.mAlign;
+        mTextAlign = paint.mTextAlign;
         mTypeface = paint.mTypeface;
         mStrokeWidth = paint.mStrokeWidth;
         mStrokeMiter = paint.mStrokeMiter;
@@ -696,7 +786,7 @@
         mStyle = 0;
         mCap = 0;
         mJoin = 0;
-        mAlign = 0;
+        mTextAlign = 0;
         mTypeface = 0;
         mStrokeWidth = 1.f;
         mStrokeMiter = 2.f;
@@ -733,6 +823,61 @@
         }
     }
 
+    /*package*/ float measureText(char[] text, int index, int count) {
+        if (mFonts.size() > 0) {
+            FontInfo mainFont = mFonts.get(0);
+            int i = index;
+            int lastIndex = index + count;
+            float total = 0f;
+            while (i < lastIndex) {
+                // always start with the main font.
+                int upTo = mainFont.mFont.canDisplayUpTo(text, i, lastIndex);
+                if (upTo == -1) {
+                    // shortcut to exit
+                    return total + mainFont.mMetrics.charsWidth(text, i, lastIndex - i);
+                } else if (upTo > 0) {
+                    total += mainFont.mMetrics.charsWidth(text, i, upTo - i);
+                    i = upTo;
+                    // don't call continue at this point. Since it is certain the main font
+                    // cannot display the font a index upTo (now ==i), we move on to the
+                    // fallback fonts directly.
+                }
+
+                // no char supported, attempt to read the next char(s) with the
+                // fallback font. In this case we only test the first character
+                // and then go back to test with the main font.
+                // Special test for 2-char characters.
+                boolean foundFont = false;
+                for (int f = 1 ; f < mFonts.size() ; f++) {
+                    FontInfo fontInfo = mFonts.get(f);
+
+                    // need to check that the font can display the character. We test
+                    // differently if the char is a high surrogate.
+                    int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1;
+                    upTo = fontInfo.mFont.canDisplayUpTo(text, i, i + charCount);
+                    if (upTo == -1) {
+                        total += fontInfo.mMetrics.charsWidth(text, i, charCount);
+                        i += charCount;
+                        foundFont = true;
+                        break;
+
+                    }
+                }
+
+                // in case no font can display the char, measure it with the main font.
+                if (foundFont == false) {
+                    int size = Character.isHighSurrogate(text[i]) ? 2 : 1;
+                    total += mainFont.mMetrics.charsWidth(text, i, size);
+                    i += size;
+                }
+            }
+        }
+
+        return 0;
+
+    }
+
+
     private static void setFlag(Paint thisPaint, int flagMask, boolean flagValue) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);