diff options
Diffstat (limited to 'tools/layoutlib/bridge/src')
22 files changed, 506 insertions, 307 deletions
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java index 7d4271b..572fdc9 100644 --- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java +++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java @@ -758,6 +758,17 @@ public final class BridgeTypedArray extends TypedArray { return s != null && ResourceHelper.parseFloatAttribute(mNames[index], s, outValue, false); } + @Override + public int getType(int index) { + if (!hasValue(index)) { + return TypedValue.TYPE_NULL; + } + ResourceValue value = mResourceData[index]; + ResourceType resourceType = value.getResourceType(); + return 0; + // TODO: fixme. + } + /** * Determines whether there is an attribute at <var>index</var>. * diff --git a/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java b/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java index a4a3b7d..21f36ce 100644 --- a/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java +++ b/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java @@ -19,6 +19,12 @@ package android.graphics; import com.android.ide.common.rendering.api.LayoutLog; import com.android.layoutlib.bridge.Bridge; +import android.graphics.Paint_Delegate.FontInfo; +import android.icu.lang.UScript; +import android.icu.lang.UScriptRun; +import android.icu.text.Bidi; +import android.icu.text.BidiRun; + import java.awt.Font; import java.awt.Graphics2D; import java.awt.Toolkit; @@ -29,13 +35,6 @@ import java.util.ArrayList; import java.util.LinkedList; import java.util.List; -import com.ibm.icu.lang.UScript; -import com.ibm.icu.lang.UScriptRun; -import com.ibm.icu.text.Bidi; -import com.ibm.icu.text.BidiRun; - -import android.graphics.Paint_Delegate.FontInfo; - /** * Render the text by breaking it into various scripts and using the right font for each script. * Can be used to measure the text without actually drawing it. diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java index e9b5d6e..af47aeb 100644 --- a/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java @@ -23,7 +23,15 @@ import com.android.tools.layoutlib.annotations.LayoutlibDelegate; import android.graphics.Shader.TileMode; +import java.awt.PaintContext; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.awt.geom.NoninvertibleTransformException; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; import java.awt.image.ColorModel; +import java.awt.image.Raster; /** * Delegate implementing the native methods of android.graphics.BitmapShader @@ -67,9 +75,9 @@ public class BitmapShader_Delegate extends Shader_Delegate { // ---- native methods ---- @LayoutlibDelegate - /*package*/ static long nativeCreate(long native_bitmap, int shaderTileModeX, + /*package*/ static long nativeCreate(Bitmap androidBitmap, int shaderTileModeX, int shaderTileModeY) { - Bitmap_Delegate bitmap = Bitmap_Delegate.getDelegate(native_bitmap); + Bitmap_Delegate bitmap = Bitmap_Delegate.getDelegate(androidBitmap); if (bitmap == null) { return 0; } @@ -83,17 +91,17 @@ public class BitmapShader_Delegate extends Shader_Delegate { // ---- Private delegate/helper methods ---- - private BitmapShader_Delegate(java.awt.image.BufferedImage image, + private BitmapShader_Delegate(BufferedImage image, TileMode tileModeX, TileMode tileModeY) { mJavaPaint = new BitmapShaderPaint(image, tileModeX, tileModeY); } private class BitmapShaderPaint implements java.awt.Paint { - private final java.awt.image.BufferedImage mImage; + private final BufferedImage mImage; private final TileMode mTileModeX; private final TileMode mTileModeY; - BitmapShaderPaint(java.awt.image.BufferedImage image, + BitmapShaderPaint(BufferedImage image, TileMode tileModeX, TileMode tileModeY) { mImage = image; mTileModeX = tileModeX; @@ -101,29 +109,24 @@ public class BitmapShader_Delegate extends Shader_Delegate { } @Override - public java.awt.PaintContext createContext( - java.awt.image.ColorModel colorModel, - java.awt.Rectangle deviceBounds, - java.awt.geom.Rectangle2D userBounds, - java.awt.geom.AffineTransform xform, - java.awt.RenderingHints hints) { - - java.awt.geom.AffineTransform canvasMatrix; + public PaintContext createContext(ColorModel colorModel, Rectangle deviceBounds, + Rectangle2D userBounds, AffineTransform xform, RenderingHints hints) { + AffineTransform canvasMatrix; try { canvasMatrix = xform.createInverse(); - } catch (java.awt.geom.NoninvertibleTransformException e) { + } catch (NoninvertibleTransformException e) { Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE, "Unable to inverse matrix in BitmapShader", e, null /*data*/); - canvasMatrix = new java.awt.geom.AffineTransform(); + canvasMatrix = new AffineTransform(); } - java.awt.geom.AffineTransform localMatrix = getLocalMatrix(); + AffineTransform localMatrix = getLocalMatrix(); try { localMatrix = localMatrix.createInverse(); - } catch (java.awt.geom.NoninvertibleTransformException e) { + } catch (NoninvertibleTransformException e) { Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE, "Unable to inverse matrix in BitmapShader", e, null /*data*/); - localMatrix = new java.awt.geom.AffineTransform(); + localMatrix = new AffineTransform(); } if (!colorModel.isCompatibleRaster(mImage.getRaster())) { @@ -134,16 +137,16 @@ public class BitmapShader_Delegate extends Shader_Delegate { return new BitmapShaderContext(canvasMatrix, localMatrix, colorModel); } - private class BitmapShaderContext implements java.awt.PaintContext { + private class BitmapShaderContext implements PaintContext { - private final java.awt.geom.AffineTransform mCanvasMatrix; - private final java.awt.geom.AffineTransform mLocalMatrix; - private final java.awt.image.ColorModel mColorModel; + private final AffineTransform mCanvasMatrix; + private final AffineTransform mLocalMatrix; + private final ColorModel mColorModel; public BitmapShaderContext( - java.awt.geom.AffineTransform canvasMatrix, - java.awt.geom.AffineTransform localMatrix, - java.awt.image.ColorModel colorModel) { + AffineTransform canvasMatrix, + AffineTransform localMatrix, + ColorModel colorModel) { mCanvasMatrix = canvasMatrix; mLocalMatrix = localMatrix; mColorModel = colorModel; @@ -154,13 +157,13 @@ public class BitmapShader_Delegate extends Shader_Delegate { } @Override - public java.awt.image.ColorModel getColorModel() { + public ColorModel getColorModel() { return mColorModel; } @Override - public java.awt.image.Raster getRaster(int x, int y, int w, int h) { - java.awt.image.BufferedImage image = new java.awt.image.BufferedImage( + public Raster getRaster(int x, int y, int w, int h) { + BufferedImage image = new BufferedImage( mColorModel, mColorModel.createCompatibleWritableRaster(w, h), mColorModel.isAlphaPremultiplied(), null); diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java index 970b9d0..874bc9d 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java @@ -16,6 +16,7 @@ package android.graphics; +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; @@ -82,6 +83,12 @@ public final class Bitmap_Delegate { return sManager.getDelegate(native_bitmap); } + @Nullable + public static Bitmap_Delegate getDelegate(@Nullable Bitmap bitmap) { + // refSkPixelRef is a hack to get the native pointer: see #nativeRefPixelRef() + return bitmap == null ? null : getDelegate(bitmap.refSkPixelRef()); + } + /** * Creates and returns a {@link Bitmap} initialized with the given file content. * @@ -180,18 +187,7 @@ public final class Bitmap_Delegate { return createBitmap(delegate, createFlags, density.getDpiValue()); } - public static int getBufferedImageType(int nativeBitmapConfig) { - switch (Config.nativeToConfig(nativeBitmapConfig)) { - case ALPHA_8: - return BufferedImage.TYPE_INT_ARGB; - case RGB_565: - return BufferedImage.TYPE_INT_ARGB; - case ARGB_4444: - return BufferedImage.TYPE_INT_ARGB; - case ARGB_8888: - return BufferedImage.TYPE_INT_ARGB; - } - + private static int getBufferedImageType() { return BufferedImage.TYPE_INT_ARGB; } @@ -218,10 +214,6 @@ public final class Bitmap_Delegate { return mHasAlpha && mConfig != Config.RGB_565; } - public boolean hasMipMap() { - // TODO: check if more checks are required as in hasAlpha. - return mHasMipMap; - } /** * Update the generationId. * @@ -236,7 +228,7 @@ public final class Bitmap_Delegate { @LayoutlibDelegate /*package*/ static Bitmap nativeCreate(int[] colors, int offset, int stride, int width, int height, int nativeConfig, boolean isMutable) { - int imageType = getBufferedImageType(nativeConfig); + int imageType = getBufferedImageType(); // create the image BufferedImage image = new BufferedImage(width, height, imageType); @@ -264,7 +256,7 @@ public final class Bitmap_Delegate { int width = srcImage.getWidth(); int height = srcImage.getHeight(); - int imageType = getBufferedImageType(nativeConfig); + int imageType = getBufferedImageType(); // create the image BufferedImage image = new BufferedImage(width, height, imageType); @@ -353,22 +345,16 @@ public final class Bitmap_Delegate { /*package*/ static boolean nativeHasAlpha(long nativeBitmap) { // get the delegate from the native int. Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return true; - } + return delegate == null || delegate.mHasAlpha; - return delegate.mHasAlpha; } @LayoutlibDelegate /*package*/ static boolean nativeHasMipMap(long nativeBitmap) { // get the delegate from the native int. Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return true; - } + return delegate == null || delegate.mHasMipMap; - return delegate.mHasMipMap; } @LayoutlibDelegate @@ -489,11 +475,6 @@ public final class Bitmap_Delegate { } @LayoutlibDelegate - /*package*/ static void nativePrepareToDraw(long nativeBitmap) { - // nothing to be done here. - } - - @LayoutlibDelegate /*package*/ static boolean nativeIsPremultiplied(long nativeBitmap) { // get the delegate from the native int. Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); @@ -579,6 +560,14 @@ public final class Bitmap_Delegate { return Arrays.equals(argb1, argb2); } + // Only used by AssetAtlasService, which we don't care about. + @LayoutlibDelegate + /*package*/ static long nativeRefPixelRef(long nativeBitmap) { + // Hack: This is called by Bitmap.refSkPixelRef() and LayoutLib uses that method to get + // the native pointer from a Bitmap. So, we return nativeBitmap here. + return nativeBitmap; + } + // ---- Private delegate/helper methods ---- private Bitmap_Delegate(BufferedImage image, Config config) { diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java index e1091f0..47acc42 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java @@ -16,6 +16,7 @@ package android.graphics; +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; @@ -114,7 +115,11 @@ public final class Canvas_Delegate { } @LayoutlibDelegate - /*package*/ static long initRaster(long nativeBitmapOrZero) { + /*package*/ static long initRaster(@Nullable Bitmap bitmap) { + long nativeBitmapOrZero = 0; + if (bitmap != null) { + nativeBitmapOrZero = bitmap.refSkPixelRef(); + } if (nativeBitmapOrZero > 0) { // get the Bitmap from the int Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(nativeBitmapOrZero); @@ -132,8 +137,7 @@ public final class Canvas_Delegate { } @LayoutlibDelegate - /*package*/ - static void native_setBitmap(long canvas, long bitmap, boolean copyState) { + /*package*/ static void native_setBitmap(long canvas, Bitmap bitmap) { Canvas_Delegate canvasDelegate = sManager.getDelegate(canvas); Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap); if (canvasDelegate == null || bitmapDelegate==null) { @@ -427,8 +431,7 @@ public final class Canvas_Delegate { canvasDelegate.mDrawFilter = DrawFilter_Delegate.getDelegate(nativeFilter); - if (canvasDelegate.mDrawFilter != null && - canvasDelegate.mDrawFilter.isSupported() == false) { + if (canvasDelegate.mDrawFilter != null && !canvasDelegate.mDrawFilter.isSupported()) { Bridge.getLog().fidelityWarning(LayoutLog.TAG_DRAWFILTER, canvasDelegate.mDrawFilter.getSupportMessage(), null, null /*data*/); } @@ -444,7 +447,7 @@ public final class Canvas_Delegate { } Rectangle rect = canvasDelegate.getSnapshot().getClip().getBounds(); - if (rect != null && rect.isEmpty() == false) { + if (rect != null && !rect.isEmpty()) { bounds.left = rect.x; bounds.top = rect.y; bounds.right = rect.x + rect.width; @@ -720,7 +723,7 @@ public final class Canvas_Delegate { } @LayoutlibDelegate - /*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, long bitmap, + /*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap, float left, float top, long nativePaintOrZero, int canvasDensity, @@ -742,7 +745,7 @@ public final class Canvas_Delegate { } @LayoutlibDelegate - /*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, long bitmap, + /*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, long nativePaintOrZero, int screenDensity, int bitmapDensity) { @@ -783,7 +786,7 @@ public final class Canvas_Delegate { } @LayoutlibDelegate - /*package*/ static void nativeDrawBitmapMatrix(long nCanvas, long nBitmap, + /*package*/ static void nativeDrawBitmapMatrix(long nCanvas, Bitmap bitmap, long nMatrix, long nPaint) { // get the delegate from the native int. Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas); @@ -795,7 +798,7 @@ public final class Canvas_Delegate { Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nPaint); // get the delegate from the native int. - Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(nBitmap); + Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap); if (bitmapDelegate == null) { return; } @@ -824,7 +827,7 @@ public final class Canvas_Delegate { } @LayoutlibDelegate - /*package*/ static void nativeDrawBitmapMesh(long nCanvas, long nBitmap, + /*package*/ static void nativeDrawBitmapMesh(long nCanvas, Bitmap bitmap, int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors, int colorOffset, long nPaint) { // FIXME @@ -1041,8 +1044,7 @@ public final class Canvas_Delegate { } /** - * Restores the {@link GcSnapshot} to <var>saveCount</var> - * @param saveCount the saveCount + * Restores the top {@link GcSnapshot} */ private void restore() { mSnapshot = mSnapshot.restore(); @@ -1105,7 +1107,7 @@ public final class Canvas_Delegate { // before drawing it. if (bitmap.getConfig() == Bitmap.Config.ALPHA_8) { fixAlpha8Bitmap(image); - } else if (bitmap.hasAlpha() == false) { + } else if (!bitmap.hasAlpha()) { // hasAlpha is merely a rendering hint. There can in fact be alpha values // in the bitmap but it should be ignored at drawing time. // There is two ways to do this: @@ -1125,7 +1127,7 @@ public final class Canvas_Delegate { } // if we can't force SRC mode, then create a temp bitmap of TYPE_RGB - if (forceSrcMode[0] == false) { + if (!forceSrcMode[0]) { image = Bitmap_Delegate.createCopy(image, BufferedImage.TYPE_INT_RGB, 0xFF); } } diff --git a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java index e16dbda..e8d34d0 100644 --- a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java @@ -90,7 +90,7 @@ public final class NinePatch_Delegate { if (oos != null) { try { oos.close(); - } catch (IOException e) { + } catch (IOException ignored) { } } } @@ -136,7 +136,7 @@ public final class NinePatch_Delegate { if (ois != null) { try { ois.close(); - } catch (IOException e) { + } catch (IOException ignored) { } } } @@ -150,15 +150,12 @@ public final class NinePatch_Delegate { @LayoutlibDelegate /*package*/ static boolean isNinePatchChunk(byte[] chunk) { NinePatchChunk chunkObject = getChunk(chunk); - if (chunkObject != null) { - return true; - } + return chunkObject != null; - return false; } @LayoutlibDelegate - /*package*/ static long validateNinePatchChunk(long bitmap, byte[] chunk) { + /*package*/ static long validateNinePatchChunk(byte[] chunk) { // the default JNI implementation only checks that the byte[] has the same // size as the C struct it represent. Since we cannot do the same check (serialization // will return different size depending on content), we do nothing. @@ -173,7 +170,7 @@ public final class NinePatch_Delegate { } @LayoutlibDelegate - /*package*/ static void nativeDraw(long canvas_instance, RectF loc, long bitmap_instance, + /*package*/ static void nativeDraw(long canvas_instance, RectF loc, Bitmap bitmap_instance, long chunk, long paint_instance_or_null, int destDensity, int srcDensity) { draw(canvas_instance, (int) loc.left, (int) loc.top, (int) loc.right, (int) loc.bottom, @@ -182,7 +179,7 @@ public final class NinePatch_Delegate { } @LayoutlibDelegate - /*package*/ static void nativeDraw(long canvas_instance, Rect loc, long bitmap_instance, + /*package*/ static void nativeDraw(long canvas_instance, Rect loc, Bitmap bitmap_instance, long chunk, long paint_instance_or_null, int destDensity, int srcDensity) { draw(canvas_instance, loc.left, loc.top, loc.right, loc.bottom, @@ -191,7 +188,7 @@ public final class NinePatch_Delegate { } @LayoutlibDelegate - /*package*/ static long nativeGetTransparentRegion(long bitmap, long chunk, Rect location) { + /*package*/ static long nativeGetTransparentRegion(Bitmap bitmap, long chunk, Rect location) { return 0; } @@ -199,7 +196,7 @@ public final class NinePatch_Delegate { private static void draw(long canvas_instance, final int left, final int top, final int right, final int bottom, - long bitmap_instance, long chunk, long paint_instance_or_null, + Bitmap bitmap_instance, long chunk, long paint_instance_or_null, final int destDensity, final int srcDensity) { // get the delegate from the native int. final Bitmap_Delegate bitmap_delegate = Bitmap_Delegate.getDelegate(bitmap_instance); diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java index 0c8c0d6..3b1e3f9 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Paint_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; @@ -83,6 +85,8 @@ public class Paint_Delegate { private float mTextScaleX; private float mTextSkewX; private int mHintingMode = Paint.HINTING_ON; + private int mHyphenEdit; + private float mLetterSpacing; // not used in actual text rendering. // Variant of the font. A paint's variant can only be compact or elegant. private FontVariant mFontVariant = FontVariant.COMPACT; @@ -100,6 +104,7 @@ public class Paint_Delegate { // ---- Public Helper methods ---- + @Nullable public static Paint_Delegate getDelegate(long native_paint) { return sManager.getDelegate(native_paint); } @@ -1088,18 +1093,107 @@ public class Paint_Delegate { @LayoutlibDelegate /*package*/ static float native_getLetterSpacing(long nativePaint) { - // TODO: throw a fidelity warning. - return 0; + Paint_Delegate delegate = sManager.getDelegate(nativePaint); + if (delegate == null) { + return 0; + } + return delegate.mLetterSpacing; } @LayoutlibDelegate /*package*/ static void native_setLetterSpacing(long nativePaint, float letterSpacing) { - // pass. + Bridge.getLog().fidelityWarning(LayoutLog.TAG_TEXT_RENDERING, + "Paint.setLetterSpacing() not supported.", null, null); + Paint_Delegate delegate = sManager.getDelegate(nativePaint); + if (delegate == null) { + return; + } + delegate.mLetterSpacing = letterSpacing; } @LayoutlibDelegate /*package*/ static void native_setFontFeatureSettings(long nativePaint, String settings) { - // pass. + Bridge.getLog().fidelityWarning(LayoutLog.TAG_TEXT_RENDERING, + "Paint.setFontFeatureSettings() not supported.", null, null); + } + + @LayoutlibDelegate + /*package*/ static int native_getHyphenEdit(long nativePaint) { + Paint_Delegate delegate = sManager.getDelegate(nativePaint); + if (delegate == null) { + return 0; + } + return delegate.mHyphenEdit; + } + + @LayoutlibDelegate + /*package*/ static void native_setHyphenEdit(long nativePaint, int hyphen) { + Paint_Delegate delegate = sManager.getDelegate(nativePaint); + if (delegate == null) { + return; + } + delegate.mHyphenEdit = hyphen; + } + + @LayoutlibDelegate + /*package*/ static boolean native_hasGlyph(long nativePaint, long nativeTypeface, int bidiFlags, + String string) { + Paint_Delegate delegate = sManager.getDelegate(nativePaint); + if (delegate == null) { + return false; + } + if (string.length() == 0) { + return false; + } + if (string.length() > 1) { + Bridge.getLog().fidelityWarning(LayoutLog.TAG_TEXT_RENDERING, + "Paint.hasGlyph() is not supported for ligatures.", null, null); + return false; + } + assert nativeTypeface == delegate.mNativeTypeface; + Typeface_Delegate typeface_delegate = Typeface_Delegate.getDelegate(nativeTypeface); + + char c = string.charAt(0); + for (Font font : typeface_delegate.getFonts(delegate.mFontVariant)) { + if (font.canDisplay(c)) { + return true; + } + } + return false; + } + + + @LayoutlibDelegate + /*package*/ static float native_getRunAdvance(long nativePaint, long nativeTypeface, + @NonNull char[] text, int start, int end, int contextStart, int contextEnd, + boolean isRtl, int offset) { + int count = end - start; + float[] advances = new float[count]; + native_getTextRunAdvances(nativePaint, nativeTypeface, text, start, count, + contextStart, contextEnd - contextStart, isRtl, advances, 0); + float sum = 0; + for (int i = 0; i < offset; i++) { + sum += advances[i]; + } + return sum; + } + + @LayoutlibDelegate + /*package*/ static int native_getOffsetForAdvance(long nativePaint, long nativeTypeface, + char[] text, int start, int end, int contextStart, int contextEnd, boolean isRtl, + float advance) { + int count = end - start; + float[] advances = new float[count]; + native_getTextRunAdvances(nativePaint, nativeTypeface, text, start, count, + contextStart, contextEnd - contextStart, isRtl, advances, 0); + float sum = 0; + int i; + for (i = 0; i < count && sum < advance; i++) { + sum += advances[i]; + } + float distanceToI = sum - advance; + float distanceToIMinus1 = advance - (sum - advances[i]); + return distanceToI > distanceToIMinus1 ? i : i - 1; } // ---- Private delegate/helper methods ---- diff --git a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java index 14e9960..0d491a0 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java @@ -81,14 +81,15 @@ public abstract class Shader_Delegate { } @LayoutlibDelegate - /*package*/ static void nativeSetLocalMatrix(long native_shader, long matrix_instance) { + /*package*/ static long 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; + return native_shader; } shaderDelegate.mLocalMatrix = Matrix_Delegate.getDelegate(matrix_instance); + return native_shader; } // ---- Private delegate/helper methods ---- diff --git a/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java b/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java index 6247dae..38171dc 100644 --- a/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java +++ b/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java @@ -19,8 +19,8 @@ package android.text; import com.android.ide.common.rendering.api.LayoutLog; import com.android.layoutlib.bridge.Bridge; import com.android.tools.layoutlib.annotations.LayoutlibDelegate; -import com.ibm.icu.text.Bidi; +import android.icu.text.Bidi; /** * Delegate used to provide new implementation for the native methods of {@link AndroidBidi} diff --git a/tools/layoutlib/bridge/src/android/text/GreedyLineBreaker.java b/tools/layoutlib/bridge/src/android/text/GreedyLineBreaker.java index c72efc2..b95cda6 100644 --- a/tools/layoutlib/bridge/src/android/text/GreedyLineBreaker.java +++ b/tools/layoutlib/bridge/src/android/text/GreedyLineBreaker.java @@ -36,7 +36,7 @@ public class GreedyLineBreaker extends LineBreaker { } @Override - public void computeBreaks(LineBreaks lineBreaks) { + public void computeBreaks(@NonNull LineBreaks lineBreaks) { BreakInfo breakInfo = new BreakInfo(); int lineNum = 0; float width = 0, printedWidth = 0; diff --git a/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java b/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java new file mode 100644 index 0000000..5a59597 --- /dev/null +++ b/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2015 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.text; + +import com.android.layoutlib.bridge.impl.DelegateManager; +import com.android.tools.layoutlib.annotations.LayoutlibDelegate; + +import java.io.File; + +/** + * Delegate that overrides implementation for certain methods in {@link android.text.StaticLayout} + * <p/> + * Through the layoutlib_create tool, selected methods of StaticLayout have been replaced + * by calls to methods of the same name in this delegate class. + */ +public class Hyphenator_Delegate { + + private static final DelegateManager<Hyphenator_Delegate> sDelegateManager = new + DelegateManager<Hyphenator_Delegate>(Hyphenator_Delegate.class); + + @LayoutlibDelegate + /*package*/ static File getSystemHyphenatorLocation() { + // FIXME + return null; + } + + /*package*/ static long loadHyphenator(String patternData) { + return sDelegateManager.addNewDelegate(new Hyphenator_Delegate()); + } +} diff --git a/tools/layoutlib/bridge/src/android/text/LineBreaker.java b/tools/layoutlib/bridge/src/android/text/LineBreaker.java index 54445a4..edeef78 100644 --- a/tools/layoutlib/bridge/src/android/text/LineBreaker.java +++ b/tools/layoutlib/bridge/src/android/text/LineBreaker.java @@ -39,6 +39,5 @@ public abstract class LineBreaker { mTabStops = tabStops; } - @NonNull public abstract void computeBreaks(@NonNull LineBreaks breakInfo); } diff --git a/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java b/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java index 86d8da3..dda8ebb 100644 --- a/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java +++ b/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java @@ -8,15 +8,15 @@ import android.graphics.BidiRenderer; import android.graphics.Paint; import android.graphics.Paint_Delegate; import android.graphics.RectF; -import android.text.StaticLayout.LineBreaks; +import android.icu.text.BreakIterator; +import android.icu.util.ULocale; import android.text.Primitive.PrimitiveType; +import android.text.StaticLayout.LineBreaks; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import com.ibm.icu.text.BreakIterator; -import com.ibm.icu.util.ULocale; import javax.swing.text.Segment; /** @@ -38,15 +38,55 @@ public class StaticLayout_Delegate { new DelegateManager<Builder>(Builder.class); @LayoutlibDelegate - /*package*/ static int nComputeLineBreaks(long nativeBuilder, - int length, float firstWidth, int firstWidthLineCount, float restWidth, - int[] variableTabStops, int defaultTabStop, boolean optimize, LineBreaks recycle, - int[] recycleBreaks, float[] recycleWidths, boolean[] recycleFlags, int recycleLength) { + /*package*/ static long nNewBuilder() { + return sBuilderManager.addNewDelegate(new Builder()); + } + + @LayoutlibDelegate + /*package*/ static void nFreeBuilder(long nativeBuilder) { + sBuilderManager.removeJavaReferenceFor(nativeBuilder); + } + + @LayoutlibDelegate + /*package*/ static void nFinishBuilder(long nativeBuilder) { + } + @LayoutlibDelegate + /*package*/ static long nLoadHyphenator(String patternData) { + return Hyphenator_Delegate.loadHyphenator(patternData); + } + + @LayoutlibDelegate + /*package*/ static void nSetLocale(long nativeBuilder, String locale, long nativeHyphenator) { Builder builder = sBuilderManager.getDelegate(nativeBuilder); + if (builder != null) { + builder.mLocale = locale; + builder.mNativeHyphenator = nativeHyphenator; + } + } + + @LayoutlibDelegate + /*package*/ static void nSetIndents(long nativeBuilder, int[] indents) { + // TODO. + } + + @LayoutlibDelegate + /*package*/ static void nSetupParagraph(long nativeBuilder, char[] text, int length, + float firstWidth, int firstWidthLineCount, float restWidth, + int[] variableTabStops, int defaultTabStop, int breakStrategy, + int hyphenationFrequency) { + Builder builder = sBuilderManager.getDelegate(nativeBuilder); + if (builder == null) { + return; + } + + builder.mText = text; + builder.mWidths = new float[length]; + // compute all possible breakpoints. BreakIterator it = BreakIterator.getLineInstance(new ULocale(builder.mLocale)); it.setText(new Segment(builder.mText, 0, length)); + // average word length in english is 5. So, initialize the possible breaks with a guess. List<Integer> breaks = new ArrayList<Integer>((int) Math.ceil(length / 5d)); int loc; @@ -54,17 +94,73 @@ public class StaticLayout_Delegate { while ((loc = it.next()) != BreakIterator.DONE) { breaks.add(loc); } - LineWidth lineWidth = new LineWidth(firstWidth, firstWidthLineCount, restWidth); TabStops tabStopCalculator = new TabStops(variableTabStops, defaultTabStop); - List<Primitive> primitives = computePrimitives(builder.mText, builder.mWidths, length, breaks); - LineBreaker lineBreaker; - if (optimize) { - lineBreaker = new OptimizingLineBreaker(primitives, lineWidth, tabStopCalculator); - } else { - lineBreaker = new GreedyLineBreaker(primitives, lineWidth, tabStopCalculator); + List<Primitive> primitives = + computePrimitives(builder.mText, builder.mWidths, length, breaks); + BreakStrategy strategy = BreakStrategy.getStrategy(breakStrategy); + switch (strategy) { + case GREEDY: + builder.mLineBreaker = + new GreedyLineBreaker(primitives, lineWidth, tabStopCalculator); + break; + case HIGH_QUALITY: + // TODO +// break; + case BALANCED: + builder.mLineBreaker = new OptimizingLineBreaker(primitives, lineWidth, + tabStopCalculator); + break; + } + } + + @LayoutlibDelegate + /*package*/ static float nAddStyleRun(long nativeBuilder, long nativePaint, long nativeTypeface, + int start, int end, boolean isRtl) { + Builder builder = sBuilderManager.getDelegate(nativeBuilder); + + int bidiFlags = isRtl ? Paint.BIDI_FORCE_RTL : Paint.BIDI_FORCE_LTR; + return builder == null ? 0 : + measureText(nativePaint, builder.mText, start, end - start, builder.mWidths, + bidiFlags); + } + + @LayoutlibDelegate + /*package*/ static void nAddMeasuredRun(long nativeBuilder, int start, int end, float[] widths) { + Builder builder = sBuilderManager.getDelegate(nativeBuilder); + if (builder != null) { + System.arraycopy(widths, start, builder.mWidths, start, end - start); + } + } + + @LayoutlibDelegate + /*package*/ static void nAddReplacementRun(long nativeBuilder, int start, int end, float width) { + Builder builder = sBuilderManager.getDelegate(nativeBuilder); + if (builder == null) { + return; + } + builder.mWidths[start] = width; + Arrays.fill(builder.mWidths, start + 1, end, 0.0f); + } + + @LayoutlibDelegate + /*package*/ static void nGetWidths(long nativeBuilder, float[] floatsArray) { + Builder builder = sBuilderManager.getDelegate(nativeBuilder); + if (builder != null) { + System.arraycopy(builder.mWidths, 0, floatsArray, 0, builder.mWidths.length); } - lineBreaker.computeBreaks(recycle); + } + + @LayoutlibDelegate + /*package*/ static int nComputeLineBreaks(long nativeBuilder, + LineBreaks recycle, int[] recycleBreaks, float[] recycleWidths, + int[] recycleFlags, int recycleLength) { + + Builder builder = sBuilderManager.getDelegate(nativeBuilder); + if (builder == null) { + return 0; + } + builder.mLineBreaker.computeBreaks(recycle); return recycle.breaks.length; } @@ -109,63 +205,6 @@ public class StaticLayout_Delegate { return primitives; } - @LayoutlibDelegate - /*package*/ static long nNewBuilder() { - return sBuilderManager.addNewDelegate(new Builder()); - } - - @LayoutlibDelegate - /*package*/ static void nFinishBuilder(long nativeBuilder) { - } - - @LayoutlibDelegate - /*package*/ static void nFreeBuilder(long nativeBuilder) { - sBuilderManager.removeJavaReferenceFor(nativeBuilder); - } - - @LayoutlibDelegate - /*package*/ static void nSetLocale(long nativeBuilder, String locale) { - Builder builder = sBuilderManager.getDelegate(nativeBuilder); - builder.mLocale = locale; - } - - @LayoutlibDelegate - /*package*/ static void nSetText(long nativeBuilder, char[] text, int length) { - Builder builder = sBuilderManager.getDelegate(nativeBuilder); - builder.mText = text; - builder.mWidths = new float[length]; - } - - - @LayoutlibDelegate - /*package*/ static float nAddStyleRun(long nativeBuilder, long nativePaint, long nativeTypeface, - int start, int end, boolean isRtl) { - Builder builder = sBuilderManager.getDelegate(nativeBuilder); - - int bidiFlags = isRtl ? Paint.BIDI_FORCE_RTL : Paint.BIDI_FORCE_LTR; - return measureText(nativePaint, builder.mText, start, end - start, builder.mWidths, bidiFlags); - } - - - @LayoutlibDelegate - /*package*/ static void nAddMeasuredRun(long nativeBuilder, int start, int end, float[] widths) { - Builder builder = sBuilderManager.getDelegate(nativeBuilder); - System.arraycopy(widths, start, builder.mWidths, start, end - start); - } - - @LayoutlibDelegate - /*package*/ static void nAddReplacementRun(long nativeBuilder, int start, int end, float width) { - Builder builder = sBuilderManager.getDelegate(nativeBuilder); - builder.mWidths[start] = width; - Arrays.fill(builder.mWidths, start + 1, end, 0.0f); - } - - @LayoutlibDelegate - /*package*/ static void nGetWidths(long nativeBuilder, float[] floatsArray) { - Builder builder = sBuilderManager.getDelegate(nativeBuilder); - System.arraycopy(builder.mWidths, 0, floatsArray, 0, builder.mWidths.length); - } - private static float measureText(long nativePaint, char []text, int index, int count, float[] widths, int bidiFlags) { Paint_Delegate paint = Paint_Delegate.getDelegate(nativePaint); @@ -174,12 +213,32 @@ public class StaticLayout_Delegate { return bounds.right - bounds.left; } + // TODO: Rename to LineBreakerRef and move everything other than LineBreaker to LineBreaker. /** * Java representation of the native Builder class. */ - static class Builder { + private static class Builder { String mLocale; char[] mText; float[] mWidths; + LineBreaker mLineBreaker; + long mNativeHyphenator; + } + + private enum BreakStrategy { + GREEDY, HIGH_QUALITY, BALANCED; + + static BreakStrategy getStrategy(int strategy) { + switch (strategy) { + case 0: + return GREEDY; + case 1: + return HIGH_QUALITY; + case 2: + return BALANCED; + default: + throw new AssertionError("Unknown break strategy: " + strategy); + } + } } } diff --git a/tools/layoutlib/bridge/src/android/util/Xml_Delegate.java b/tools/layoutlib/bridge/src/android/util/Xml_Delegate.java index a193330..213e848 100644 --- a/tools/layoutlib/bridge/src/android/util/Xml_Delegate.java +++ b/tools/layoutlib/bridge/src/android/util/Xml_Delegate.java @@ -17,9 +17,9 @@ package android.util; import com.android.layoutlib.bridge.impl.DelegateManager; +import com.android.layoutlib.bridge.impl.ParserFactory; import com.android.tools.layoutlib.annotations.LayoutlibDelegate; -import org.kxml2.io.KXmlParser; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -37,11 +37,7 @@ public class Xml_Delegate { @LayoutlibDelegate /*package*/ static XmlPullParser newPullParser() { try { - KXmlParser parser = new KXmlParser(); - // The prebuilt kxml2 library with the IDE doesn't support DOCECL. -// parser.setFeature(XmlPullParser.FEATURE_PROCESS_DOCDECL, true); - parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); - return parser; + return ParserFactory.instantiateParser(null); } catch (XmlPullParserException e) { throw new AssertionError(); } 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 c6d60f8..af67a43 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java @@ -16,9 +16,6 @@ package com.android.layoutlib.bridge; -import static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN; -import static com.android.ide.common.rendering.api.Result.Status.SUCCESS; - import com.android.annotations.NonNull; import com.android.ide.common.rendering.api.Capability; import com.android.ide.common.rendering.api.DrawableParams; @@ -36,13 +33,12 @@ import com.android.resources.ResourceType; import com.android.tools.layoutlib.create.MethodAdapter; import com.android.tools.layoutlib.create.OverrideMethod; import com.android.util.Pair; -import com.ibm.icu.util.ULocale; -import libcore.io.MemoryMappedFile_Delegate; import android.content.res.BridgeAssetManager; import android.graphics.Bitmap; import android.graphics.FontFamily_Delegate; import android.graphics.Typeface_Delegate; +import android.icu.util.ULocale; import android.os.Looper; import android.os.Looper_Accessor; import android.view.View; @@ -60,6 +56,11 @@ import java.util.HashMap; import java.util.Map; import java.util.concurrent.locks.ReentrantLock; +import libcore.io.MemoryMappedFile_Delegate; + +import static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN; +import static com.android.ide.common.rendering.api.Result.Status.SUCCESS; + /** * Main entry point of the LayoutLib Bridge. * <p/>To use this bridge, simply instantiate an object of type {@link Bridge} and call diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/AndroidLocale.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/AndroidLocale.java index ea5f1ea..e589d9e 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/AndroidLocale.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/AndroidLocale.java @@ -16,9 +16,9 @@ package com.android.layoutlib.bridge.android; -import java.util.Locale; +import android.icu.util.ULocale; -import com.ibm.icu.util.ULocale; +import java.util.Locale; /** * This class provides an alternate implementation for {@code java.util.Locale#toLanguageTag} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java index 04aadff..16f477b 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java @@ -24,6 +24,7 @@ import org.xmlpull.v1.XmlPullParserException; import android.content.Context; import android.content.pm.ApplicationInfo; import android.util.AttributeSet; +import android.util.DisplayMetrics; import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; @@ -32,6 +33,14 @@ public class NavigationBar extends CustomBar { /** Navigation bar background color attribute name. */ private static final String ATTR_COLOR = "navigationBarColor"; + // These correspond to @dimen/navigation_side_padding in the system ui code. + private static final int PADDING_WIDTH_DEFAULT = 36; + private static final int PADDING_WIDTH_SW360 = 40; + private static final int PADDING_WIDTH_SW400 = 50; + // These corresponds to @dimen/navigation_key_width in the system ui code. + private static final int WIDTH_DEFAULT = 36; + private static final int WIDTH_SW360 = 40; + private static final int WIDTH_SW600 = 48; /** * Constructor to be used when creating the {@link NavigationBar} as a regular control. @@ -45,7 +54,7 @@ public class NavigationBar extends CustomBar { ((BridgeContext) context).getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL, (context.getApplicationInfo().flags & ApplicationInfo.FLAG_SUPPORTS_RTL) != 0, - context.getApplicationInfo().targetSdkVersion); + 0); } public NavigationBar(BridgeContext context, Density density, int orientation, boolean isRtl, @@ -61,19 +70,70 @@ public class NavigationBar extends CustomBar { // We do know the order though. // 0 is a spacer. int back = 1; - int recent = 3; + int recent = 5; if (orientation == LinearLayout.VERTICAL || (isRtl && !rtlEnabled)) { // If RTL is enabled, then layoutlib mirrors the layout for us. - back = 3; + back = 5; recent = 1; } //noinspection SpellCheckingInspection - loadIcon(back, "ic_sysbar_back.png", density, isRtl); + loadIcon(back, "ic_sysbar_back.png", density, isRtl); //noinspection SpellCheckingInspection - loadIcon(2, "ic_sysbar_home.png", density, isRtl); + loadIcon(3, "ic_sysbar_home.png", density, isRtl); //noinspection SpellCheckingInspection loadIcon(recent, "ic_sysbar_recent.png", density, isRtl); + setupNavBar(context, orientation); + } + + private void setupNavBar(BridgeContext context, int orientation) { + View leftPadding = getChildAt(0); + View rightPadding = getChildAt(6); + setSize(context, leftPadding, orientation, getSidePadding(context)); + setSize(context, rightPadding, orientation, getSidePadding(context)); + for (int i = 1; i < 6; i += 2) { + View navButton = getChildAt(i); + setSize(context, navButton, orientation, getWidth(context)); + } + } + + private static void setSize(BridgeContext context, View view, int orientation, int size) { + size *= context.getMetrics().density; + LayoutParams layoutParams = (LayoutParams) view.getLayoutParams(); + if (orientation == HORIZONTAL) { + layoutParams.width = size; + } else { + layoutParams.height = size; + } + view.setLayoutParams(layoutParams); + } + + private static int getSidePadding(BridgeContext context) { + DisplayMetrics metrics = context.getMetrics(); + float sw = metrics.widthPixels > metrics.heightPixels + ? metrics.heightPixels : metrics.widthPixels; + sw /= metrics.density; + if (sw >= 400) { + return PADDING_WIDTH_SW400; + } + if (sw >= 360) { + return PADDING_WIDTH_SW360; + } + return PADDING_WIDTH_DEFAULT; + } + + private static int getWidth(BridgeContext context) { + DisplayMetrics metrics = context.getMetrics(); + float sw = metrics.widthPixels > metrics.heightPixels + ? metrics.heightPixels : metrics.widthPixels; + sw /= metrics.density; + if (sw >= 600) { + return WIDTH_SW600; + } + if (sw >= 360) { + return WIDTH_SW360; + } + return WIDTH_DEFAULT; } @Override diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java index 261cc98..dbee9ea 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java @@ -16,6 +16,7 @@ package com.android.layoutlib.bridge.impl; +import com.android.annotations.Nullable; import com.android.layoutlib.bridge.util.Debug; import com.android.layoutlib.bridge.util.SparseWeakArray; @@ -48,7 +49,7 @@ import java.util.List; * int -> Delegate class link. * * Native methods usually always have the int as parameters. The first thing the delegate method - * will do is call {@link #getDelegate(int)} to get the Java object matching the int. + * will do is call {@link #getDelegate(long)} to get the Java object matching the int. * * Typical native init methods are returning a new int back to the Java class, so * {@link #addNewDelegate(Object)} does the same. @@ -57,7 +58,7 @@ import java.util.List; * the Java object needs to count as a reference (even though it only holds an int), we use the * following mechanism: * - * - {@link #addNewDelegate(Object)} and {@link #removeJavaReferenceFor(int)} adds and removes + * - {@link #addNewDelegate(Object)} and {@link #removeJavaReferenceFor(long)} adds and removes * the delegate to/from a list. This list hold the reference and prevents the GC from reclaiming * the delegate. * @@ -70,12 +71,13 @@ import java.util.List; * @param <T> the delegate class to manage */ public final class DelegateManager<T> { + @SuppressWarnings("FieldCanBeLocal") private final Class<T> mClass; private final SparseWeakArray<T> mDelegates = new SparseWeakArray<T>(); /** list used to store delegates when their main object holds a reference to them. * This is to ensure that the WeakReference in the SparseWeakArray doesn't get GC'ed * @see #addNewDelegate(Object) - * @see #removeJavaReferenceFor(int) + * @see #removeJavaReferenceFor(long) */ private final List<T> mJavaReferences = new ArrayList<T>(); private int mDelegateCounter = 0; @@ -94,6 +96,7 @@ public final class DelegateManager<T> { * @param native_object the native int. * @return the delegate or null if not found. */ + @Nullable public T getDelegate(long native_object) { if (native_object > 0) { T delegate = mDelegates.get(native_object); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java index 803849f..6ca22b0 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java @@ -17,7 +17,10 @@ package com.android.layoutlib.bridge.impl; -import org.kxml2.io.KXmlParser; +import com.android.annotations.NonNull; +import com.android.annotations.Nullable; +import com.android.ide.common.rendering.api.LayoutlibCallback; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -35,24 +38,35 @@ import java.io.InputStream; */ public class ParserFactory { + public final static boolean LOG_PARSER = false; + private final static String ENCODING = "UTF-8"; //$NON-NLS-1$ - public final static boolean LOG_PARSER = false; + // Used to get a new XmlPullParser from the client. + @Nullable + private static LayoutlibCallback sLayoutlibCallback; - public static XmlPullParser create(File f) + public static void setLayoutlibCallback(@Nullable LayoutlibCallback callback) { + sLayoutlibCallback = callback; + } + + @NonNull + public static XmlPullParser create(@NonNull File f) throws XmlPullParserException, FileNotFoundException { InputStream stream = new FileInputStream(f); return create(stream, f.getName(), f.length()); } - public static XmlPullParser create(InputStream stream, String name) + @NonNull + public static XmlPullParser create(@NonNull InputStream stream, @Nullable String name) throws XmlPullParserException { return create(stream, name, -1); } - private static XmlPullParser create(InputStream stream, String name, long size) - throws XmlPullParserException { - KXmlParser parser = instantiateParser(name); + @NonNull + private static XmlPullParser create(@NonNull InputStream stream, @Nullable String name, + long size) throws XmlPullParserException { + XmlPullParser parser = instantiateParser(name); stream = readAndClose(stream, name, size); @@ -60,19 +74,20 @@ public class ParserFactory { return parser; } - private static KXmlParser instantiateParser(String name) throws XmlPullParserException { - KXmlParser parser; - if (name != null) { - parser = new CustomParser(name); - } else { - parser = new KXmlParser(); + @NonNull + public static XmlPullParser instantiateParser(@Nullable String name) + throws XmlPullParserException { + if (sLayoutlibCallback == null) { + throw new XmlPullParserException("ParserFactory not initialized."); } + XmlPullParser parser = sLayoutlibCallback.createParser(name); parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); return parser; } - private static InputStream readAndClose(InputStream stream, String name, long size) - throws XmlPullParserException { + @NonNull + private static InputStream readAndClose(@NonNull InputStream stream, @Nullable String name, + long size) throws XmlPullParserException { // just a sanity check. It's doubtful we'll have such big files! if (size > Integer.MAX_VALUE) { throw new XmlPullParserException("File " + name + " is too big to be parsed"); @@ -121,22 +136,8 @@ public class ParserFactory { } finally { try { bufferedStream.close(); - } catch (IOException e) { + } catch (IOException ignored) { } } } - - private static class CustomParser extends KXmlParser { - private final String mName; - - CustomParser(String name) { - super(); - mName = name; - } - - @Override - public String toString() { - return mName; - } - } } 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 c708316..66b0023 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 @@ -39,6 +39,8 @@ import android.view.inputmethod.InputMethodManager_Accessor; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; +import javax.swing.text.html.parser.Parser; + import static com.android.ide.common.rendering.api.Result.Status.ERROR_LOCK_INTERRUPTED; import static com.android.ide.common.rendering.api.Result.Status.ERROR_TIMEOUT; import static com.android.ide.common.rendering.api.Result.Status.SUCCESS; @@ -99,6 +101,9 @@ public abstract class RenderAction<T extends RenderParams> extends FrameworkReso return result; } + // setup the ParserFactory + ParserFactory.setLayoutlibCallback(mParams.getLayoutlibCallback()); + HardwareConfig hardwareConfig = mParams.getHardwareConfig(); // setup the display Metrics. @@ -271,6 +276,7 @@ public abstract class RenderAction<T extends RenderParams> extends FrameworkReso mContext.getRenderResources().setFrameworkResourceIdProvider(null); mContext.getRenderResources().setLogger(null); } + ParserFactory.setLayoutlibCallback(null); } diff --git a/tools/layoutlib/bridge/src/libcore/icu/DateIntervalFormat_Delegate.java b/tools/layoutlib/bridge/src/libcore/icu/DateIntervalFormat_Delegate.java deleted file mode 100644 index d94c205..0000000 --- a/tools/layoutlib/bridge/src/libcore/icu/DateIntervalFormat_Delegate.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2013 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 libcore.icu; - -import java.text.FieldPosition; - -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 com.ibm.icu.text.DateIntervalFormat; -import com.ibm.icu.util.DateInterval; -import com.ibm.icu.util.TimeZone; -import com.ibm.icu.util.ULocale; - -public class DateIntervalFormat_Delegate { - - // ---- delegate manager ---- - private static final DelegateManager<DateIntervalFormat_Delegate> sManager = - new DelegateManager<DateIntervalFormat_Delegate>(DateIntervalFormat_Delegate.class); - - // ---- delegate data ---- - private DateIntervalFormat mFormat; - - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/static String formatDateInterval(long address, long fromDate, long toDate) { - DateIntervalFormat_Delegate delegate = sManager.getDelegate((int)address); - if (delegate == null) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "Unable for find native DateIntervalFormat", null); - return null; - } - DateInterval interval = new DateInterval(fromDate, toDate); - StringBuffer sb = new StringBuffer(); - FieldPosition pos = new FieldPosition(0); - delegate.mFormat.format(interval, sb, pos); - return sb.toString(); - } - - @LayoutlibDelegate - /*package*/ static long createDateIntervalFormat(String skeleton, String localeName, - String tzName) { - TimeZone prevDefaultTz = TimeZone.getDefault(); - TimeZone.setDefault(TimeZone.getTimeZone(tzName)); - DateIntervalFormat_Delegate newDelegate = new DateIntervalFormat_Delegate(); - newDelegate.mFormat = - DateIntervalFormat.getInstance(skeleton, new ULocale(localeName)); - TimeZone.setDefault(prevDefaultTz); - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static void destroyDateIntervalFormat(long address) { - sManager.removeJavaReferenceFor((int)address); - } - -} diff --git a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java index b8b5fed..9c58010 100644 --- a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java +++ b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java @@ -17,9 +17,11 @@ package libcore.icu; import com.android.tools.layoutlib.annotations.LayoutlibDelegate; -import com.ibm.icu.text.DateTimePatternGenerator; -import com.ibm.icu.util.Currency; -import com.ibm.icu.util.ULocale; + +import android.icu.text.DateTimePatternGenerator; +import android.icu.util.Currency; +import android.icu.util.ULocale; +import android.icu.util.VersionInfo; import java.util.Locale; @@ -53,18 +55,19 @@ public class ICU_Delegate { } @LayoutlibDelegate + @SuppressWarnings("deprecation") /*package*/ static String getCldrVersion() { - return "22.1.1"; // TODO: check what the right value should be. + return VersionInfo.ICU_DATA_VERSION.toString(); } @LayoutlibDelegate /*package*/ static String getIcuVersion() { - return "unknown_layoutlib"; + return VersionInfo.ICU_VERSION.toString(); } @LayoutlibDelegate /*package*/ static String getUnicodeVersion() { - return "5.2"; + return VersionInfo.UNICODE_7_0.toString(); } @LayoutlibDelegate @@ -181,8 +184,8 @@ public class ICU_Delegate { /*package*/ static boolean initLocaleDataNative(String locale, LocaleData result) { // Used by Calendar. - result.firstDayOfWeek = Integer.valueOf(1); - result.minimalDaysInFirstWeek = Integer.valueOf(1); + result.firstDayOfWeek = 1; + result.minimalDaysInFirstWeek = 1; // Used by DateFormatSymbols. result.amPm = new String[] { "AM", "PM" }; @@ -252,4 +255,9 @@ public class ICU_Delegate { /*package*/ static String getDefaultLocale() { return ICU.getDefaultLocale(); } + + @LayoutlibDelegate + /*package*/ static String getTZDataVersion() { + return ICU.getTZDataVersion(); + } } |