diff options
24 files changed, 1136 insertions, 359 deletions
diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java index 1d6e52c7cc1e..05fd4c8ab69f 100644 --- a/core/java/android/widget/TimePickerClockDelegate.java +++ b/core/java/android/widget/TimePickerClockDelegate.java @@ -69,10 +69,8 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate impl private static final int[] ATTRS_TEXT_COLOR = new int[] {R.attr.textColor}; private static final int[] ATTRS_DISABLED_ALPHA = new int[] {R.attr.disabledAlpha}; - // LayoutLib relies on these constants. Change TimePickerClockDelegate_Delegate if - // modifying these. - static final int AM = 0; - static final int PM = 1; + private static final int AM = 0; + private static final int PM = 1; private static final int HOURS_IN_HALF_DAY = 12; diff --git a/tools/layoutlib/.idea/inspectionProfiles/Project_Default.xml b/tools/layoutlib/.idea/inspectionProfiles/Project_Default.xml index 5bb3e3e47922..3681f2aaf3f1 100644 --- a/tools/layoutlib/.idea/inspectionProfiles/Project_Default.xml +++ b/tools/layoutlib/.idea/inspectionProfiles/Project_Default.xml @@ -1,4 +1,3 @@ -<?xml version="1.0" encoding="UTF-8"?> <component name="InspectionProjectProfileManager"> <profile version="1.0" is_locked="false"> <option name="myName" value="Project Default" /> @@ -8,6 +7,15 @@ <option name="CHECK_TRY_CATCH_SECTION" value="true" /> <option name="CHECK_METHOD_BODY" value="true" /> </inspection_tool> + <inspection_tool class="LoggerInitializedWithForeignClass" enabled="false" level="WARNING" enabled_by_default="false"> + <option name="loggerClassName" value="org.apache.log4j.Logger,org.slf4j.LoggerFactory,org.apache.commons.logging.LogFactory,java.util.logging.Logger" /> + <option name="loggerFactoryMethodName" value="getLogger,getLogger,getLog,getLogger" /> + </inspection_tool> <inspection_tool class="ToArrayCallWithZeroLengthArrayArgument" enabled="false" level="WARNING" enabled_by_default="false" /> + <inspection_tool class="WeakerAccess" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS" value="false" /> + <option name="SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES" value="false" /> + <option name="SUGGEST_PRIVATE_FOR_INNERS" value="true" /> + </inspection_tool> </profile> </component>
\ No newline at end of file diff --git a/tools/layoutlib/.idea/misc.xml b/tools/layoutlib/.idea/misc.xml index b474bdc00013..44b47f2c91d4 100644 --- a/tools/layoutlib/.idea/misc.xml +++ b/tools/layoutlib/.idea/misc.xml @@ -37,7 +37,7 @@ </value> </option> </component> - <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" default="false" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK"> + <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="false" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK"> <output url="file://$PROJECT_DIR$/out" /> </component> </project>
\ No newline at end of file diff --git a/tools/layoutlib/.idea/runConfigurations/Bridge_quick.xml b/tools/layoutlib/.idea/runConfigurations/Bridge_quick.xml index 4f0eb8dc23a4..b402849f22a3 100644 --- a/tools/layoutlib/.idea/runConfigurations/Bridge_quick.xml +++ b/tools/layoutlib/.idea/runConfigurations/Bridge_quick.xml @@ -26,4 +26,4 @@ <ConfigurationWrapper RunnerId="Run" /> <method /> </configuration> -</component>
\ No newline at end of file +</component> diff --git a/tools/layoutlib/Android.mk b/tools/layoutlib/Android.mk index 53bfc1581e53..5e57a2533657 100644 --- a/tools/layoutlib/Android.mk +++ b/tools/layoutlib/Android.mk @@ -16,8 +16,6 @@ LOCAL_PATH := $(my-dir) include $(CLEAR_VARS) -LOCAL_JAVACFLAGS := -source 6 -target 6 - # # Define rules to build temp_layoutlib.jar, which contains a subset of # the classes in framework.jar. The layoutlib_create tool is used to diff --git a/tools/layoutlib/bridge/Android.mk b/tools/layoutlib/bridge/Android.mk index 0dbdd5627e63..3dd8002bcff5 100644 --- a/tools/layoutlib/bridge/Android.mk +++ b/tools/layoutlib/bridge/Android.mk @@ -18,8 +18,6 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := $(call all-java-files-under,src) LOCAL_JAVA_RESOURCE_DIRS := resources -LOCAL_JAVACFLAGS := -source 6 -target 6 - LOCAL_JAVA_LIBRARIES := \ layoutlib_api-prebuilt \ diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java b/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java index 0e392436d748..fe46480f25ab 100644 --- a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java +++ b/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java @@ -49,6 +49,7 @@ import java.io.FileNotFoundException; import java.io.InputStream; import java.util.Iterator; +@SuppressWarnings("deprecation") public final class BridgeResources extends Resources { private BridgeContext mContext; @@ -70,6 +71,7 @@ public final class BridgeResources extends Resources { @Override public boolean markSupported() { + //noinspection SimplifiableIfStatement if (mFakeMarkSupport) { // this is needed so that BitmapFactory doesn't wrap this in a BufferedInputStream. return true; @@ -595,7 +597,6 @@ public final class BridgeResources extends Resources { if (value != null) { ResourceValue resValue = value.getSecond(); - assert resValue != null; if (resValue != null) { String v = resValue.getValue(); if (v != null) { diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java index 07376828a1fe..e3bb3e318749 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java @@ -17,9 +17,14 @@ package android.graphics; import com.android.ide.common.rendering.api.LayoutLog; +import com.android.ide.common.rendering.api.RenderResources; +import com.android.ide.common.rendering.api.ResourceValue; import com.android.layoutlib.bridge.Bridge; +import com.android.layoutlib.bridge.android.BridgeContext; import com.android.layoutlib.bridge.impl.DelegateManager; +import com.android.layoutlib.bridge.impl.RenderAction; import com.android.resources.Density; +import com.android.resources.ResourceType; import com.android.tools.layoutlib.annotations.LayoutlibDelegate; import android.annotation.Nullable; @@ -38,6 +43,7 @@ import java.util.EnumSet; import java.util.Set; import javax.imageio.ImageIO; +import libcore.util.NativeAllocationRegistry_Delegate; /** * Delegate implementing the native methods of android.graphics.Bitmap @@ -62,12 +68,13 @@ public final class Bitmap_Delegate { // ---- delegate manager ---- private static final DelegateManager<Bitmap_Delegate> sManager = new DelegateManager<Bitmap_Delegate>(Bitmap_Delegate.class); + private static long sFinalizer = -1; // ---- delegate helper data ---- // ---- delegate data ---- private final Config mConfig; - private BufferedImage mImage; + private final BufferedImage mImage; private boolean mHasAlpha = true; private boolean mHasMipMap = false; // TODO: check the default. private boolean mIsPremultiplied = true; @@ -114,10 +121,25 @@ public final class Bitmap_Delegate { * @see Bitmap#isMutable() * @see Bitmap#getDensity() */ - public static Bitmap createBitmap(File input, Set<BitmapCreateFlags> createFlags, + private static Bitmap createBitmap(File input, Set<BitmapCreateFlags> createFlags, Density density) throws IOException { // create a delegate with the content of the file. - Bitmap_Delegate delegate = new Bitmap_Delegate(ImageIO.read(input), Config.ARGB_8888); + BufferedImage image = ImageIO.read(input); + if (image == null && input.exists()) { + // There was a problem decoding the image, or the decoder isn't registered. Webp maybe. + // Replace with a broken image icon. + BridgeContext currentContext = RenderAction.getCurrentContext(); + if (currentContext != null) { + RenderResources resources = currentContext.getRenderResources(); + ResourceValue broken = resources.getFrameworkResource(ResourceType.DRAWABLE, + "ic_menu_report_image"); + File brokenFile = new File(broken.getValue()); + if (brokenFile.exists()) { + image = ImageIO.read(brokenFile); + } + } + } + Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ARGB_8888); return createBitmap(delegate, createFlags, density.getDpiValue()); } @@ -281,8 +303,13 @@ public final class Bitmap_Delegate { } @LayoutlibDelegate - /*package*/ static void nativeDestructor(long nativeBitmap) { - sManager.removeJavaReferenceFor(nativeBitmap); + /*package*/ static long nativeGetNativeFinalizer() { + synchronized (Bitmap_Delegate.class) { + if (sFinalizer == -1) { + sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(sManager::removeJavaReferenceFor); + } + return sFinalizer; + } } @LayoutlibDelegate diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java index ba0d399ce52f..c4fbd562812a 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java @@ -21,6 +21,7 @@ import com.android.layoutlib.bridge.Bridge; import com.android.layoutlib.bridge.impl.DelegateManager; import com.android.layoutlib.bridge.impl.GcSnapshot; import com.android.layoutlib.bridge.impl.PorterDuffUtility; +import com.android.ninepatch.NinePatchChunk; import com.android.tools.layoutlib.annotations.LayoutlibDelegate; import android.annotation.Nullable; @@ -38,6 +39,8 @@ import java.awt.geom.Arc2D; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; +import libcore.util.NativeAllocationRegistry_Delegate; + /** * Delegate implementing the native methods of android.graphics.Canvas @@ -57,6 +60,7 @@ public final class Canvas_Delegate { // ---- delegate manager ---- private static final DelegateManager<Canvas_Delegate> sManager = new DelegateManager<Canvas_Delegate>(Canvas_Delegate.class); + private static long sFinalizer = -1; // ---- delegate helper data ---- @@ -160,6 +164,9 @@ public final class Canvas_Delegate { } @LayoutlibDelegate + /*package*/ static void native_setHighContrastText(long nativeCanvas, boolean highContrastText){} + + @LayoutlibDelegate /*package*/ static int native_getWidth(long nativeCanvas) { // get the delegate from the native int. Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); @@ -749,6 +756,61 @@ public final class Canvas_Delegate { } @LayoutlibDelegate + /*package*/ static void native_drawRegion(long nativeCanvas, long nativeRegion, + long nativePaint) { + // FIXME + Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, + "Some canvas paths may not be drawn", null, null); + } + + @LayoutlibDelegate + /*package*/ static void native_drawNinePatch(Canvas thisCanvas, long nativeCanvas, + long nativeBitmap, long ninePatch, final float dstLeft, final float dstTop, + final float dstRight, final float dstBottom, long nativePaintOrZero, + final int screenDensity, final int bitmapDensity) { + + // get the delegate from the native int. + final Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(nativeBitmap); + if (bitmapDelegate == null) { + return; + } + + byte[] c = NinePatch_Delegate.getChunk(ninePatch); + if (c == null) { + // not a 9-patch? + BufferedImage image = bitmapDelegate.getImage(); + drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero, 0, 0, image.getWidth(), + image.getHeight(), (int) dstLeft, (int) dstTop, (int) dstRight, + (int) dstBottom); + return; + } + + final NinePatchChunk chunkObject = NinePatch_Delegate.getChunk(c); + assert chunkObject != null; + if (chunkObject == null) { + return; + } + + Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas); + if (canvasDelegate == null) { + return; + } + + // this one can be null + Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nativePaintOrZero); + + canvasDelegate.getSnapshot().draw(new GcSnapshot.Drawable() { + @Override + public void draw(Graphics2D graphics, Paint_Delegate paint) { + chunkObject.draw(bitmapDelegate.getImage(), graphics, (int) dstLeft, (int) dstTop, + (int) (dstRight - dstLeft), (int) (dstBottom - dstTop), screenDensity, + bitmapDensity); + } + }, paintDelegate, true, false); + + } + + @LayoutlibDelegate /*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap, float left, float top, long nativePaintOrZero, @@ -934,20 +996,21 @@ public final class Canvas_Delegate { } @LayoutlibDelegate - /*package*/ static void finalizer(long nativeCanvas) { - // get the delegate from the native int so that it can be disposed. - Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return; + /*package*/ static long getNativeFinalizer() { + synchronized (Canvas_Delegate.class) { + if (sFinalizer == -1) { + sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(nativePtr -> { + Canvas_Delegate delegate = sManager.getDelegate(nativePtr); + if (delegate != null) { + delegate.dispose(); + } + sManager.removeJavaReferenceFor(nativePtr); + }); + } } - - canvasDelegate.dispose(); - - // remove it from the manager. - sManager.removeJavaReferenceFor(nativeCanvas); + return sFinalizer; } - // ---- Private delegate/helper methods ---- /** diff --git a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java index b6588b65b5ae..0e66baaf7cbf 100644 --- a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java @@ -33,13 +33,13 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Scanner; import java.util.Set; @@ -213,7 +213,7 @@ public class FontFamily_Delegate { return mValid; } - /*package*/ static Font loadFont(String path) { + private static Font loadFont(String path) { if (path.startsWith(SYSTEM_FONTS) ) { String relativePath = path.substring(SYSTEM_FONTS.length()); File f = new File(sFontLocation, relativePath); @@ -270,16 +270,12 @@ public class FontFamily_Delegate { } @LayoutlibDelegate - /*package*/ static boolean nAddFont(long nativeFamily, final String path) { + /*package*/ static boolean nAddFont(long nativeFamily, final String path, int ttcIndex) { + // FIXME: support ttc fonts. Hack JRE?? final FontFamily_Delegate delegate = getDelegate(nativeFamily); if (delegate != null) { if (sFontLocation == null) { - delegate.mPostInitRunnables.add(new Runnable() { - @Override - public void run() { - delegate.addFont(path); - } - }); + delegate.mPostInitRunnables.add(() -> delegate.addFont(path)); return true; } return delegate.addFont(path); @@ -289,18 +285,18 @@ public class FontFamily_Delegate { @LayoutlibDelegate /*package*/ static boolean nAddFontWeightStyle(long nativeFamily, - final String path, final int index, final List<FontListParser.Axis> axes, + ByteBuffer buffer, final List<FontListParser.Axis> axes, final int weight, final boolean isItalic) { - // 'index' and 'axes' are not supported by java.awt.Font + assert false : "The only client of this method has been overriden."; + return false; + } + + static boolean addFont(long nativeFamily, final String path, final int weight, + final boolean isItalic) { final FontFamily_Delegate delegate = getDelegate(nativeFamily); if (delegate != null) { if (sFontLocation == null) { - delegate.mPostInitRunnables.add(new Runnable() { - @Override - public void run() { - delegate.addFont(path, weight, isItalic); - } - }); + delegate.mPostInitRunnables.add(() -> delegate.addFont(path, weight, isItalic)); return true; } return delegate.addFont(path, weight, isItalic); @@ -311,6 +307,9 @@ public class FontFamily_Delegate { @LayoutlibDelegate /*package*/ static boolean nAddFontFromAsset(long nativeFamily, AssetManager mgr, String path) { FontFamily_Delegate ffd = sManager.getDelegate(nativeFamily); + if (ffd == null) { + return false; + } ffd.mValid = true; if (mgr == null) { return false; @@ -454,6 +453,7 @@ public class FontFamily_Delegate { private FontInfo deriveFont(@NonNull FontInfo srcFont, @NonNull FontInfo outFont) { int desiredWeight = outFont.mWeight; int srcWeight = srcFont.mWeight; + assert srcFont.mFont != null; Font derivedFont = srcFont.mFont; // Embolden the font if required. if (desiredWeight >= BOLD_FONT_WEIGHT && desiredWeight - srcWeight > BOLD_FONT_WEIGHT_DELTA / 2) { diff --git a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java index e8d34d0562aa..1f0eb3bab55b 100644 --- a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java @@ -169,77 +169,18 @@ public final class NinePatch_Delegate { sManager.removeJavaReferenceFor(chunk); } - @LayoutlibDelegate - /*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, - bitmap_instance, chunk, paint_instance_or_null, - destDensity, srcDensity); - } - - @LayoutlibDelegate - /*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, - bitmap_instance, chunk, paint_instance_or_null, - destDensity, srcDensity); - } @LayoutlibDelegate /*package*/ static long nativeGetTransparentRegion(Bitmap bitmap, long chunk, Rect location) { return 0; } - // ---- Private Helper methods ---- - - private static void draw(long canvas_instance, - final int left, final int top, final int right, final int bottom, - 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); - if (bitmap_delegate == null) { - return; - } - - byte[] c = null; - NinePatch_Delegate delegate = sManager.getDelegate(chunk); + static byte[] getChunk(long nativeNinePatch) { + NinePatch_Delegate delegate = sManager.getDelegate(nativeNinePatch); if (delegate != null) { - c = delegate.chunk; - } - if (c == null) { - // not a 9-patch? - BufferedImage image = bitmap_delegate.getImage(); - Canvas_Delegate.native_drawBitmap(null, canvas_instance, bitmap_instance, - 0f, 0f, (float)image.getWidth(), (float)image.getHeight(), - (float)left, (float)top, (float)right, (float)bottom, - paint_instance_or_null, destDensity, srcDensity); - return; + return delegate.chunk; } + return null; + } - final NinePatchChunk chunkObject = getChunk(c); - assert chunkObject != null; - if (chunkObject == null) { - return; - } - - Canvas_Delegate canvas_delegate = Canvas_Delegate.getDelegate(canvas_instance); - if (canvas_delegate == null) { - return; - } - - // this one can be null - Paint_Delegate paint_delegate = Paint_Delegate.getDelegate(paint_instance_or_null); - - canvas_delegate.getSnapshot().draw(new GcSnapshot.Drawable() { - @Override - public void draw(Graphics2D graphics, Paint_Delegate paint) { - chunkObject.draw(bitmap_delegate.getImage(), graphics, - left, top, right - left, bottom - top, destDensity, srcDensity); - } - }, paint_delegate, true /*compositeOnly*/, false /*forceSrcMode*/); - - } } diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java index dbd45c4f68be..514d7852bd05 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java @@ -39,6 +39,8 @@ import java.util.Collections; import java.util.List; import java.util.Locale; +import libcore.util.NativeAllocationRegistry_Delegate; + /** * Delegate implementing the native methods of android.graphics.Paint * @@ -65,6 +67,7 @@ public class Paint_Delegate { // ---- delegate manager ---- private static final DelegateManager<Paint_Delegate> sManager = new DelegateManager<Paint_Delegate>(Paint_Delegate.class); + private static long sFinalizer = -1; // ---- delegate helper data ---- @@ -250,9 +253,9 @@ public class Paint_Delegate { // ---- native methods ---- @LayoutlibDelegate - /*package*/ static int getFlags(Paint thisPaint) { + /*package*/ static int nGetFlags(Paint thisPaint, long nativePaint) { // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance()); + Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { return 0; } @@ -263,9 +266,9 @@ public class Paint_Delegate { @LayoutlibDelegate - /*package*/ static void setFlags(Paint thisPaint, int flags) { + /*package*/ static void nSetFlags(Paint thisPaint, long nativePaint, int flags) { // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance()); + Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { return; } @@ -274,14 +277,14 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static void setFilterBitmap(Paint thisPaint, boolean filter) { - setFlag(thisPaint, Paint.FILTER_BITMAP_FLAG, filter); + /*package*/ static void nSetFilterBitmap(Paint thisPaint, long nativePaint, boolean filter) { + setFlag(nativePaint, Paint.FILTER_BITMAP_FLAG, filter); } @LayoutlibDelegate - /*package*/ static int getHinting(Paint thisPaint) { + /*package*/ static int nGetHinting(Paint thisPaint, long nativePaint) { // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance()); + Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { return Paint.HINTING_ON; } @@ -290,9 +293,9 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static void setHinting(Paint thisPaint, int mode) { + /*package*/ static void nSetHinting(Paint thisPaint, long nativePaint, int mode) { // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance()); + Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { return; } @@ -301,44 +304,48 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static void setAntiAlias(Paint thisPaint, boolean aa) { - setFlag(thisPaint, Paint.ANTI_ALIAS_FLAG, aa); + /*package*/ static void nSetAntiAlias(Paint thisPaint, long nativePaint, boolean aa) { + setFlag(nativePaint, Paint.ANTI_ALIAS_FLAG, aa); } @LayoutlibDelegate - /*package*/ static void setSubpixelText(Paint thisPaint, boolean subpixelText) { - setFlag(thisPaint, Paint.SUBPIXEL_TEXT_FLAG, subpixelText); + /*package*/ static void nSetSubpixelText(Paint thisPaint, long nativePaint, + boolean subpixelText) { + setFlag(nativePaint, Paint.SUBPIXEL_TEXT_FLAG, subpixelText); } @LayoutlibDelegate - /*package*/ static void setUnderlineText(Paint thisPaint, boolean underlineText) { - setFlag(thisPaint, Paint.UNDERLINE_TEXT_FLAG, underlineText); + /*package*/ static void nSetUnderlineText(Paint thisPaint, long nativePaint, + boolean underlineText) { + setFlag(nativePaint, Paint.UNDERLINE_TEXT_FLAG, underlineText); } @LayoutlibDelegate - /*package*/ static void setStrikeThruText(Paint thisPaint, boolean strikeThruText) { - setFlag(thisPaint, Paint.STRIKE_THRU_TEXT_FLAG, strikeThruText); + /*package*/ static void nSetStrikeThruText(Paint thisPaint, long nativePaint, + boolean strikeThruText) { + setFlag(nativePaint, Paint.STRIKE_THRU_TEXT_FLAG, strikeThruText); } @LayoutlibDelegate - /*package*/ static void setFakeBoldText(Paint thisPaint, boolean fakeBoldText) { - setFlag(thisPaint, Paint.FAKE_BOLD_TEXT_FLAG, fakeBoldText); + /*package*/ static void nSetFakeBoldText(Paint thisPaint, long nativePaint, + boolean fakeBoldText) { + setFlag(nativePaint, Paint.FAKE_BOLD_TEXT_FLAG, fakeBoldText); } @LayoutlibDelegate - /*package*/ static void setDither(Paint thisPaint, boolean dither) { - setFlag(thisPaint, Paint.DITHER_FLAG, dither); + /*package*/ static void nSetDither(Paint thisPaint, long nativePaint, boolean dither) { + setFlag(nativePaint, Paint.DITHER_FLAG, dither); } @LayoutlibDelegate - /*package*/ static void setLinearText(Paint thisPaint, boolean linearText) { - setFlag(thisPaint, Paint.LINEAR_TEXT_FLAG, linearText); + /*package*/ static void nSetLinearText(Paint thisPaint, long nativePaint, boolean linearText) { + setFlag(nativePaint, Paint.LINEAR_TEXT_FLAG, linearText); } @LayoutlibDelegate - /*package*/ static int getColor(Paint thisPaint) { + /*package*/ static int nGetColor(Paint thisPaint, long nativePaint) { // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance()); + Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { return 0; } @@ -347,9 +354,9 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static void setColor(Paint thisPaint, int color) { + /*package*/ static void nSetColor(Paint thisPaint, long nativePaint, int color) { // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance()); + Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { return; } @@ -358,9 +365,9 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static int getAlpha(Paint thisPaint) { + /*package*/ static int nGetAlpha(Paint thisPaint, long nativePaint) { // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance()); + Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { return 0; } @@ -369,9 +376,9 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static void setAlpha(Paint thisPaint, int a) { + /*package*/ static void nSetAlpha(Paint thisPaint, long nativePaint, int a) { // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance()); + Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { return; } @@ -380,9 +387,9 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static float getStrokeWidth(Paint thisPaint) { + /*package*/ static float nGetStrokeWidth(Paint thisPaint, long nativePaint) { // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance()); + Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { return 1.f; } @@ -391,9 +398,9 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static void setStrokeWidth(Paint thisPaint, float width) { + /*package*/ static void nSetStrokeWidth(Paint thisPaint, long nativePaint, float width) { // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance()); + Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { return; } @@ -402,9 +409,9 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static float getStrokeMiter(Paint thisPaint) { + /*package*/ static float nGetStrokeMiter(Paint thisPaint, long nativePaint) { // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance()); + Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { return 1.f; } @@ -413,9 +420,9 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static void setStrokeMiter(Paint thisPaint, float miter) { + /*package*/ static void nSetStrokeMiter(Paint thisPaint, long nativePaint, float miter) { // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance()); + Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { return; } @@ -424,7 +431,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static void native_setShadowLayer(long paint, float radius, float dx, float dy, + /*package*/ static void nSetShadowLayer(long paint, float radius, float dx, float dy, int color) { // FIXME Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, @@ -432,7 +439,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static boolean native_hasShadowLayer(long paint) { + /*package*/ static boolean nHasShadowLayer(long paint) { // FIXME Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, "Paint.hasShadowLayer is not supported.", null, null /*data*/); @@ -440,16 +447,17 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static boolean isElegantTextHeight(Paint thisPaint) { + /*package*/ static boolean nIsElegantTextHeight(Paint thisPaint, long nativePaint) { // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance()); + Paint_Delegate delegate = sManager.getDelegate(nativePaint); return delegate != null && delegate.mFontVariant == FontVariant.ELEGANT; } @LayoutlibDelegate - /*package*/ static void setElegantTextHeight(Paint thisPaint, boolean elegant) { + /*package*/ static void nSetElegantTextHeight(Paint thisPaint, long nativePaint, + boolean elegant) { // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance()); + Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { return; } @@ -458,9 +466,9 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static float getTextSize(Paint thisPaint) { + /*package*/ static float nGetTextSize(Paint thisPaint, long nativePaint) { // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance()); + Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { return 1.f; } @@ -469,9 +477,9 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static void setTextSize(Paint thisPaint, float textSize) { + /*package*/ static void nSetTextSize(Paint thisPaint, long nativePaint, float textSize) { // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance()); + Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { return; } @@ -483,9 +491,9 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static float getTextScaleX(Paint thisPaint) { + /*package*/ static float nGetTextScaleX(Paint thisPaint, long nativePaint) { // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance()); + Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { return 1.f; } @@ -494,9 +502,9 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static void setTextScaleX(Paint thisPaint, float scaleX) { + /*package*/ static void nSetTextScaleX(Paint thisPaint, long nativePaint, float scaleX) { // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance()); + Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { return; } @@ -508,9 +516,9 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static float getTextSkewX(Paint thisPaint) { + /*package*/ static float nGetTextSkewX(Paint thisPaint, long nativePaint) { // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance()); + Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { return 1.f; } @@ -519,9 +527,9 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static void setTextSkewX(Paint thisPaint, float skewX) { + /*package*/ static void nSetTextSkewX(Paint thisPaint, long nativePaint, float skewX) { // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance()); + Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { return; } @@ -533,9 +541,9 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static float ascent(Paint thisPaint) { + /*package*/ static float nAscent(Paint thisPaint, long nativePaint, long nativeTypeface) { // get the delegate - Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance()); + Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { return 0; } @@ -550,9 +558,9 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static float descent(Paint thisPaint) { + /*package*/ static float nDescent(Paint thisPaint, long nativePaint, long nativeTypeface) { // get the delegate - Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance()); + Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { return 0; } @@ -567,9 +575,10 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static float getFontMetrics(Paint thisPaint, FontMetrics metrics) { + /*package*/ static float nGetFontMetrics(Paint thisPaint, long nativePaint, long nativeTypeface, + FontMetrics metrics) { // get the delegate - Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance()); + Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { return 0; } @@ -578,9 +587,10 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static int getFontMetricsInt(Paint thisPaint, FontMetricsInt fmi) { + /*package*/ static int nGetFontMetricsInt(Paint thisPaint, long nativePaint, + long nativeTypeface, FontMetricsInt fmi) { // get the delegate - Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance()); + Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { return 0; } @@ -603,31 +613,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static float native_measureText(Paint thisPaint, char[] text, int index, - int count, int bidiFlags) { - // get the delegate - Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance()); - if (delegate == null) { - return 0; - } - - RectF bounds = delegate.measureText(text, index, count, null, 0, bidiFlags); - return bounds.right - bounds.left; - } - - @LayoutlibDelegate - /*package*/ static float native_measureText(Paint thisPaint, String text, int start, int end, - int bidiFlags) { - return native_measureText(thisPaint, text.toCharArray(), start, end - start, bidiFlags); - } - - @LayoutlibDelegate - /*package*/ static float native_measureText(Paint thisPaint, String text, int bidiFlags) { - return native_measureText(thisPaint, text.toCharArray(), 0, text.length(), bidiFlags); - } - - @LayoutlibDelegate - /*package*/ static int native_breakText(long nativePaint, long nativeTypeface, char[] text, + /*package*/ static int nBreakText(long nativePaint, long nativeTypeface, char[] text, int index, int count, float maxWidth, int bidiFlags, float[] measuredWidth) { // get the delegate @@ -669,21 +655,21 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static int native_breakText(long nativePaint, long nativeTypeface, String text, + /*package*/ static int nBreakText(long nativePaint, long nativeTypeface, String text, boolean measureForwards, float maxWidth, int bidiFlags, float[] measuredWidth) { - return native_breakText(nativePaint, nativeTypeface, text.toCharArray(), 0, text.length(), + return nBreakText(nativePaint, nativeTypeface, text.toCharArray(), 0, text.length(), maxWidth, bidiFlags, measuredWidth); } @LayoutlibDelegate - /*package*/ static long native_init() { + /*package*/ static long nInit() { Paint_Delegate newDelegate = new Paint_Delegate(); return sManager.addNewDelegate(newDelegate); } @LayoutlibDelegate - /*package*/ static long native_initWithPaint(long paint) { + /*package*/ static long nInitWithPaint(long paint) { // get the delegate from the native int. Paint_Delegate delegate = sManager.getDelegate(paint); if (delegate == null) { @@ -695,7 +681,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static void native_reset(long native_object) { + /*package*/ static void nReset(long native_object) { // get the delegate from the native int. Paint_Delegate delegate = sManager.getDelegate(native_object); if (delegate == null) { @@ -706,7 +692,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static void native_set(long native_dst, long native_src) { + /*package*/ static void nSet(long native_dst, long native_src) { // get the delegate from the native int. Paint_Delegate delegate_dst = sManager.getDelegate(native_dst); if (delegate_dst == null) { @@ -723,7 +709,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static int native_getStyle(long native_object) { + /*package*/ static int nGetStyle(long native_object) { // get the delegate from the native int. Paint_Delegate delegate = sManager.getDelegate(native_object); if (delegate == null) { @@ -734,7 +720,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static void native_setStyle(long native_object, int style) { + /*package*/ static void nSetStyle(long native_object, int style) { // get the delegate from the native int. Paint_Delegate delegate = sManager.getDelegate(native_object); if (delegate == null) { @@ -745,7 +731,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static int native_getStrokeCap(long native_object) { + /*package*/ static int nGetStrokeCap(long native_object) { // get the delegate from the native int. Paint_Delegate delegate = sManager.getDelegate(native_object); if (delegate == null) { @@ -756,7 +742,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static void native_setStrokeCap(long native_object, int cap) { + /*package*/ static void nSetStrokeCap(long native_object, int cap) { // get the delegate from the native int. Paint_Delegate delegate = sManager.getDelegate(native_object); if (delegate == null) { @@ -767,7 +753,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static int native_getStrokeJoin(long native_object) { + /*package*/ static int nGetStrokeJoin(long native_object) { // get the delegate from the native int. Paint_Delegate delegate = sManager.getDelegate(native_object); if (delegate == null) { @@ -778,7 +764,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static void native_setStrokeJoin(long native_object, int join) { + /*package*/ static void nSetStrokeJoin(long native_object, int join) { // get the delegate from the native int. Paint_Delegate delegate = sManager.getDelegate(native_object); if (delegate == null) { @@ -789,7 +775,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static boolean native_getFillPath(long native_object, long src, long dst) { + /*package*/ static boolean nGetFillPath(long native_object, long src, long dst) { Paint_Delegate paint = sManager.getDelegate(native_object); if (paint == null) { return false; @@ -815,7 +801,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static long native_setShader(long native_object, long shader) { + /*package*/ static long nSetShader(long native_object, long shader) { // get the delegate from the native int. Paint_Delegate delegate = sManager.getDelegate(native_object); if (delegate == null) { @@ -828,7 +814,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static long native_setColorFilter(long native_object, long filter) { + /*package*/ static long nSetColorFilter(long native_object, long filter) { // get the delegate from the native int. Paint_Delegate delegate = sManager.getDelegate(native_object); if (delegate == null) { @@ -847,7 +833,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static long native_setXfermode(long native_object, long xfermode) { + /*package*/ static long nSetXfermode(long native_object, long xfermode) { // get the delegate from the native int. Paint_Delegate delegate = sManager.getDelegate(native_object); if (delegate == null) { @@ -860,7 +846,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static long native_setPathEffect(long native_object, long effect) { + /*package*/ static long nSetPathEffect(long native_object, long effect) { // get the delegate from the native int. Paint_Delegate delegate = sManager.getDelegate(native_object); if (delegate == null) { @@ -873,7 +859,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static long native_setMaskFilter(long native_object, long maskfilter) { + /*package*/ static long nSetMaskFilter(long native_object, long maskfilter) { // get the delegate from the native int. Paint_Delegate delegate = sManager.getDelegate(native_object); if (delegate == null) { @@ -892,7 +878,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static long native_setTypeface(long native_object, long typeface) { + /*package*/ static long nSetTypeface(long native_object, long typeface) { // get the delegate from the native int. Paint_Delegate delegate = sManager.getDelegate(native_object); if (delegate == null) { @@ -909,7 +895,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static long native_setRasterizer(long native_object, long rasterizer) { + /*package*/ static long nSetRasterizer(long native_object, long rasterizer) { // get the delegate from the native int. Paint_Delegate delegate = sManager.getDelegate(native_object); if (delegate == null) { @@ -928,7 +914,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static int native_getTextAlign(long native_object) { + /*package*/ static int nGetTextAlign(long native_object) { // get the delegate from the native int. Paint_Delegate delegate = sManager.getDelegate(native_object); if (delegate == null) { @@ -939,7 +925,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static void native_setTextAlign(long native_object, int align) { + /*package*/ static void nSetTextAlign(long native_object, int align) { // get the delegate from the native int. Paint_Delegate delegate = sManager.getDelegate(native_object); if (delegate == null) { @@ -950,58 +936,27 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static void native_setTextLocale(long native_object, String locale) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return; - } - - delegate.setTextLocale(locale); - } - - @LayoutlibDelegate - /*package*/ static int native_getTextWidths(long native_object, long native_typeface, - char[] text, int index, int count, int bidiFlags, float[] widths) { - - if (widths != null) { - for (int i = 0; i< count; i++) { - widths[i]=0; - } - } + /*package*/ static int nSetTextLocales(long native_object, String locale) { // get the delegate from the native int. Paint_Delegate delegate = sManager.getDelegate(native_object); if (delegate == null) { return 0; } - // native_typeface is passed here since Framework's old implementation did not have the - // typeface object associated with the Paint. Since, we follow the new framework way, - // we store the typeface with the paint and use it directly. - assert (native_typeface == delegate.mNativeTypeface); - - RectF bounds = delegate.measureText(text, index, count, widths, 0, bidiFlags); - return ((int) (bounds.right - bounds.left)); - } - - @LayoutlibDelegate - /*package*/ static int native_getTextWidths(long native_object, long native_typeface, - String text, int start, int end, int bidiFlags, float[] widths) { - return native_getTextWidths(native_object, native_typeface, text.toCharArray(), start, - end - start, bidiFlags, widths); + delegate.setTextLocale(locale); + return 0; } @LayoutlibDelegate - /* package */static int native_getTextGlyphs(long native_object, String text, int start, - int end, int contextStart, int contextEnd, int flags, char[] glyphs) { + /*package*/ static void nSetTextLocalesByMinikinLangListId(long paintPtr, + int mMinikinLangListId) { // FIXME - return 0; } @LayoutlibDelegate - /*package*/ static float native_getTextRunAdvances(long native_object, long native_typeface, + /*package*/ static float nGetTextAdvances(long native_object, long native_typeface, char[] text, int index, int count, int contextIndex, int contextCount, - boolean isRtl, float[] advances, int advancesIndex) { + int bidiFlags, float[] advances, int advancesIndex) { if (advances != null) for (int i = advancesIndex; i< advancesIndex+count; i++) @@ -1017,25 +972,25 @@ public class Paint_Delegate { // we store the typeface with the paint and use it directly. assert (native_typeface == delegate.mNativeTypeface); - RectF bounds = delegate.measureText(text, index, count, advances, advancesIndex, isRtl); + RectF bounds = delegate.measureText(text, index, count, advances, advancesIndex, bidiFlags); return bounds.right - bounds.left; } @LayoutlibDelegate - /*package*/ static float native_getTextRunAdvances(long native_object, long native_typeface, + /*package*/ static float nGetTextAdvances(long native_object, long native_typeface, String text, int start, int end, int contextStart, int contextEnd, - boolean isRtl, float[] advances, int advancesIndex) { + int bidiFlags, float[] advances, int advancesIndex) { // FIXME: support contextStart and contextEnd int count = end - start; char[] buffer = TemporaryBuffer.obtain(count); TextUtils.getChars(text, start, end, buffer, 0); - return native_getTextRunAdvances(native_object, native_typeface, buffer, 0, count, - contextStart, contextEnd - contextStart, isRtl, advances, advancesIndex); + return nGetTextAdvances(native_object, native_typeface, buffer, 0, count, + contextStart, contextEnd - contextStart, bidiFlags, advances, advancesIndex); } @LayoutlibDelegate - /*package*/ static int native_getTextRunCursor(Paint thisPaint, long native_object, char[] text, + /*package*/ static int nGetTextRunCursor(Paint thisPaint, long native_object, char[] text, int contextStart, int contextLength, int flags, int offset, int cursorOpt) { // FIXME Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, @@ -1044,7 +999,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static int native_getTextRunCursor(Paint thisPaint, long native_object, String text, + /*package*/ static int nGetTextRunCursor(Paint thisPaint, long native_object, String text, int contextStart, int contextEnd, int flags, int offset, int cursorOpt) { // FIXME Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, @@ -1053,7 +1008,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static void native_getTextPath(long native_object, long native_typeface, + /*package*/ static void nGetTextPath(long native_object, long native_typeface, int bidiFlags, char[] text, int index, int count, float x, float y, long path) { // FIXME Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, @@ -1061,7 +1016,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static void native_getTextPath(long native_object, long native_typeface, + /*package*/ static void nGetTextPath(long native_object, long native_typeface, int bidiFlags, String text, int start, int end, float x, float y, long path) { // FIXME Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, @@ -1069,14 +1024,14 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static void nativeGetStringBounds(long nativePaint, long native_typeface, + /*package*/ static void nGetStringBounds(long nativePaint, long native_typeface, String text, int start, int end, int bidiFlags, Rect bounds) { - nativeGetCharArrayBounds(nativePaint, native_typeface, text.toCharArray(), start, + nGetCharArrayBounds(nativePaint, native_typeface, text.toCharArray(), start, end - start, bidiFlags, bounds); } @LayoutlibDelegate - /*package*/ static void nativeGetCharArrayBounds(long nativePaint, long native_typeface, + /*package*/ static void nGetCharArrayBounds(long nativePaint, long native_typeface, char[] text, int index, int count, int bidiFlags, Rect bounds) { // get the delegate from the native int. @@ -1092,12 +1047,18 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static void finalizer(long nativePaint) { - sManager.removeJavaReferenceFor(nativePaint); + /*package*/ static long nGetNativeFinalizer() { + synchronized (Paint_Delegate.class) { + if (sFinalizer == -1) { + sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer( + sManager::removeJavaReferenceFor); + } + } + return sFinalizer; } @LayoutlibDelegate - /*package*/ static float native_getLetterSpacing(long nativePaint) { + /*package*/ static float nGetLetterSpacing(long nativePaint) { Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { return 0; @@ -1106,7 +1067,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static void native_setLetterSpacing(long nativePaint, float letterSpacing) { + /*package*/ static void nSetLetterSpacing(long nativePaint, float letterSpacing) { Bridge.getLog().fidelityWarning(LayoutLog.TAG_TEXT_RENDERING, "Paint.setLetterSpacing() not supported.", null, null); Paint_Delegate delegate = sManager.getDelegate(nativePaint); @@ -1117,13 +1078,13 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static void native_setFontFeatureSettings(long nativePaint, String settings) { + /*package*/ static void nSetFontFeatureSettings(long nativePaint, String settings) { Bridge.getLog().fidelityWarning(LayoutLog.TAG_TEXT_RENDERING, "Paint.setFontFeatureSettings() not supported.", null, null); } @LayoutlibDelegate - /*package*/ static int native_getHyphenEdit(long nativePaint) { + /*package*/ static int nGetHyphenEdit(long nativePaint) { Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { return 0; @@ -1132,7 +1093,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static void native_setHyphenEdit(long nativePaint, int hyphen) { + /*package*/ static void nSetHyphenEdit(long nativePaint, int hyphen) { Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { return; @@ -1141,7 +1102,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static boolean native_hasGlyph(long nativePaint, long nativeTypeface, int bidiFlags, + /*package*/ static boolean nHasGlyph(long nativePaint, long nativeTypeface, int bidiFlags, String string) { Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { @@ -1169,13 +1130,14 @@ public class Paint_Delegate { @LayoutlibDelegate - /*package*/ static float native_getRunAdvance(long nativePaint, long nativeTypeface, + /*package*/ static float nGetRunAdvance(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); + int bidiFlags = isRtl ? Paint.BIDI_FORCE_RTL : Paint.BIDI_FORCE_LTR; + nGetTextAdvances(nativePaint, nativeTypeface, text, start, count, + contextStart, contextEnd - contextStart, bidiFlags, advances, 0); int startOffset = offset - start; // offset from start. float sum = 0; for (int i = 0; i < startOffset; i++) { @@ -1185,13 +1147,14 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static int native_getOffsetForAdvance(long nativePaint, long nativeTypeface, + /*package*/ static int nGetOffsetForAdvance(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); + int bidiFlags = isRtl ? Paint.BIDI_FORCE_RTL : Paint.BIDI_FORCE_LTR; + nGetTextAdvances(nativePaint, nativeTypeface, text, start, count, + contextStart, contextEnd - contextStart, bidiFlags, advances, 0); float sum = 0; int i; for (i = 0; i < count && sum < advance; i++) { @@ -1359,9 +1322,9 @@ public class Paint_Delegate { mLocale = new Locale(locale); } - private static void setFlag(Paint thisPaint, int flagMask, boolean flagValue) { + private static void setFlag(long nativePaint, int flagMask, boolean flagValue) { // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance()); + Paint_Delegate delegate = sManager.getDelegate(nativePaint); if (delegate == null) { return; } diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java index a10ac00fc356..e1da27ba3497 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java @@ -75,7 +75,7 @@ public final class Path_Delegate { return sManager.getDelegate(nPath); } - public Shape getJavaShape() { + public Path2D getJavaShape() { return mPath; } diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java index 85e65e690dc7..5cd34f6e000f 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java @@ -24,8 +24,10 @@ import android.graphics.FontFamily_Delegate.FontVariant; import java.awt.Font; import java.io.File; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; +import java.util.Map; import static android.graphics.FontFamily_Delegate.getFontLocation; @@ -205,6 +207,17 @@ public final class Typeface_Delegate { return new File(getFontLocation()); } + @LayoutlibDelegate + /*package*/ static FontFamily makeFamilyFromParsed(FontListParser.Family family, + Map<String, ByteBuffer> bufferForPath) { + FontFamily fontFamily = new FontFamily(family.lang, family.variant); + for (FontListParser.Font font : family.fonts) { + FontFamily_Delegate.addFont(fontFamily.mNativePtr, font.fontName, font.weight, + font.isItalic); + } + return fontFamily; + } + // ---- Private delegate/helper methods ---- private Typeface_Delegate(@NonNull FontFamily_Delegate[] fontFamilies, int style) { diff --git a/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java b/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java index 44ce7311a95c..fcd63ea993c8 100644 --- a/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java +++ b/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java @@ -25,7 +25,7 @@ import java.nio.ByteBuffer; /** * Delegate that overrides implementation for certain methods in {@link android.text.Hyphenator} * <p/> - * Through the layoutlib_create tool, selected methods of StaticLayout have been replaced + * Through the layoutlib_create tool, selected methods of Hyphenator have been replaced * by calls to methods of the same name in this delegate class. */ public class Hyphenator_Delegate { @@ -39,7 +39,8 @@ public class Hyphenator_Delegate { return null; } - /*package*/ static long loadHyphenator(ByteBuffer buf, int offset) { + /*package*/ @SuppressWarnings("UnusedParameters") // TODO implement this. + static long loadHyphenator(ByteBuffer buffer, int offset) { return sDelegateManager.addNewDelegate(new Hyphenator_Delegate()); } } diff --git a/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java b/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java new file mode 100644 index 000000000000..d3af837ffd29 --- /dev/null +++ b/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java @@ -0,0 +1,757 @@ +/* + * 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.util; + +import com.android.ide.common.rendering.api.LayoutLog; +import com.android.layoutlib.bridge.Bridge; +import com.android.layoutlib.bridge.impl.DelegateManager; +import com.android.tools.layoutlib.annotations.LayoutlibDelegate; + +import android.annotation.NonNull; +import android.graphics.Path_Delegate; + +import java.awt.geom.Path2D; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Delegate that provides implementation for native methods in {@link android.util.PathParser} + * <p/> + * Through the layoutlib_create tool, selected methods of PathParser have been replaced by calls to + * methods of the same name in this delegate class. + * + * Most of the code has been taken from the implementation in + * {@code tools/base/sdk-common/src/main/java/com/android/ide/common/vectordrawable/PathParser.java} + * revision be6fe89a3b686db5a75e7e692a148699973957f3 + */ +public class PathParser_Delegate { + + private static final Logger LOGGER = Logger.getLogger("PathParser"); + + // ---- Builder delegate manager ---- + private static final DelegateManager<PathParser_Delegate> sManager = + new DelegateManager<PathParser_Delegate>(PathParser_Delegate.class); + + // ---- delegate data ---- + @NonNull + private PathDataNode[] mPathDataNodes; + + private PathParser_Delegate(@NonNull PathDataNode[] nodes) { + mPathDataNodes = nodes; + } + + @LayoutlibDelegate + /*package*/ static boolean nParseStringForPath(long pathPtr, @NonNull String pathString, int + stringLength) { + Path_Delegate path_delegate = Path_Delegate.getDelegate(pathPtr); + if (path_delegate == null) { + return false; + } + assert pathString.length() == stringLength; + PathDataNode.nodesToPath(createNodesFromPathData(pathString), path_delegate.getJavaShape()); + return true; + } + + @LayoutlibDelegate + /*package*/ static void nCreatePathFromPathData(long outPathPtr, long pathData) { + Path_Delegate path_delegate = Path_Delegate.getDelegate(outPathPtr); + PathParser_Delegate source = sManager.getDelegate(outPathPtr); + if (source == null || path_delegate == null) { + return; + } + PathDataNode.nodesToPath(source.mPathDataNodes, path_delegate.getJavaShape()); + } + + @LayoutlibDelegate + /*package*/ static long nCreateEmptyPathData() { + PathParser_Delegate newDelegate = new PathParser_Delegate(new PathDataNode[0]); + return sManager.addNewDelegate(newDelegate); + } + + @LayoutlibDelegate + /*package*/ static long nCreatePathData(long nativePtr) { + PathParser_Delegate source = sManager.getDelegate(nativePtr); + if (source == null) { + return 0; + } + PathParser_Delegate dest = new PathParser_Delegate(deepCopyNodes(source.mPathDataNodes)); + return sManager.addNewDelegate(dest); + } + + @LayoutlibDelegate + /*package*/ static long nCreatePathDataFromString(@NonNull String pathString, + int stringLength) { + assert pathString.length() == stringLength : "Inconsistent path string length."; + PathDataNode[] nodes = createNodesFromPathData(pathString); + PathParser_Delegate delegate = new PathParser_Delegate(nodes); + return sManager.addNewDelegate(delegate); + + } + + @LayoutlibDelegate + /*package*/ static boolean nInterpolatePathData(long outDataPtr, long fromDataPtr, + long toDataPtr, float fraction) { + PathParser_Delegate out = sManager.getDelegate(outDataPtr); + PathParser_Delegate from = sManager.getDelegate(fromDataPtr); + PathParser_Delegate to = sManager.getDelegate(toDataPtr); + if (out == null || from == null || to == null) { + return false; + } + int length = from.mPathDataNodes.length; + if (length != to.mPathDataNodes.length) { + Bridge.getLog().error(LayoutLog.TAG_BROKEN, + "Cannot interpolate path data with different lengths (from " + length + " to " + + to.mPathDataNodes.length + ").", null); + return false; + } + if (out.mPathDataNodes.length != length) { + out.mPathDataNodes = new PathDataNode[length]; + } + for (int i = 0; i < length; i++) { + out.mPathDataNodes[i].interpolatePathDataNode(from.mPathDataNodes[i], + to.mPathDataNodes[i], fraction); + } + return true; + } + + @LayoutlibDelegate + /*package*/ static void nFinalize(long nativePtr) { + sManager.removeJavaReferenceFor(nativePtr); + } + + @LayoutlibDelegate + /*package*/ static boolean nCanMorph(long fromDataPtr, long toDataPtr) { + Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, "morphing path data isn't " + + "supported", null, null); + return false; + } + + @LayoutlibDelegate + /*package*/ static void nSetPathData(long outDataPtr, long fromDataPtr) { + PathParser_Delegate out = sManager.getDelegate(outDataPtr); + PathParser_Delegate from = sManager.getDelegate(fromDataPtr); + if (from == null || out == null) { + return; + } + out.mPathDataNodes = deepCopyNodes(from.mPathDataNodes); + } + + /** + * @param pathData The string representing a path, the same as "d" string in svg file. + * + * @return an array of the PathDataNode. + */ + @NonNull + private static PathDataNode[] createNodesFromPathData(@NonNull String pathData) { + int start = 0; + int end = 1; + + ArrayList<PathDataNode> list = new ArrayList<PathDataNode>(); + while (end < pathData.length()) { + end = nextStart(pathData, end); + String s = pathData.substring(start, end).trim(); + if (s.length() > 0) { + float[] val = getFloats(s); + addNode(list, s.charAt(0), val); + } + + start = end; + end++; + } + if ((end - start) == 1 && start < pathData.length()) { + addNode(list, pathData.charAt(start), new float[0]); + } + return list.toArray(new PathDataNode[list.size()]); + } + + /** + * @param source The array of PathDataNode to be duplicated. + * + * @return a deep copy of the <code>source</code>. + */ + @NonNull + private static PathDataNode[] deepCopyNodes(@NonNull PathDataNode[] source) { + PathDataNode[] copy = new PathDataNode[source.length]; + for (int i = 0; i < source.length; i++) { + copy[i] = new PathDataNode(source[i]); + } + return copy; + } + + private static int nextStart(@NonNull String s, int end) { + char c; + + while (end < s.length()) { + c = s.charAt(end); + // Note that 'e' or 'E' are not valid path commands, but could be + // used for floating point numbers' scientific notation. + // Therefore, when searching for next command, we should ignore 'e' + // and 'E'. + if ((((c - 'A') * (c - 'Z') <= 0) || ((c - 'a') * (c - 'z') <= 0)) + && c != 'e' && c != 'E') { + return end; + } + end++; + } + return end; + } + + /** + * Calculate the position of the next comma or space or negative sign + * + * @param s the string to search + * @param start the position to start searching + * @param result the result of the extraction, including the position of the the starting + * position of next number, whether it is ending with a '-'. + */ + private static void extract(@NonNull String s, int start, @NonNull ExtractFloatResult result) { + // Now looking for ' ', ',', '.' or '-' from the start. + int currentIndex = start; + boolean foundSeparator = false; + result.mEndWithNegOrDot = false; + boolean secondDot = false; + boolean isExponential = false; + for (; currentIndex < s.length(); currentIndex++) { + boolean isPrevExponential = isExponential; + isExponential = false; + char currentChar = s.charAt(currentIndex); + switch (currentChar) { + case ' ': + case ',': + foundSeparator = true; + break; + case '-': + // The negative sign following a 'e' or 'E' is not a separator. + if (currentIndex != start && !isPrevExponential) { + foundSeparator = true; + result.mEndWithNegOrDot = true; + } + break; + case '.': + if (!secondDot) { + secondDot = true; + } else { + // This is the second dot, and it is considered as a separator. + foundSeparator = true; + result.mEndWithNegOrDot = true; + } + break; + case 'e': + case 'E': + isExponential = true; + break; + } + if (foundSeparator) { + break; + } + } + // When there is nothing found, then we put the end position to the end + // of the string. + result.mEndPosition = currentIndex; + } + + /** + * Parse the floats in the string. This is an optimized version of + * parseFloat(s.split(",|\\s")); + * + * @param s the string containing a command and list of floats + * + * @return array of floats + */ + @NonNull + private static float[] getFloats(@NonNull String s) { + if (s.charAt(0) == 'z' || s.charAt(0) == 'Z') { + return new float[0]; + } + try { + float[] results = new float[s.length()]; + int count = 0; + int startPosition = 1; + int endPosition; + + ExtractFloatResult result = new ExtractFloatResult(); + int totalLength = s.length(); + + // The startPosition should always be the first character of the + // current number, and endPosition is the character after the current + // number. + while (startPosition < totalLength) { + extract(s, startPosition, result); + endPosition = result.mEndPosition; + + if (startPosition < endPosition) { + results[count++] = Float.parseFloat( + s.substring(startPosition, endPosition)); + } + + if (result.mEndWithNegOrDot) { + // Keep the '-' or '.' sign with next number. + startPosition = endPosition; + } else { + startPosition = endPosition + 1; + } + } + return Arrays.copyOf(results, count); + } catch (NumberFormatException e) { + throw new RuntimeException("error in parsing \"" + s + "\"", e); + } + } + + + private static void addNode(@NonNull ArrayList<PathDataNode> list, char cmd, + @NonNull float[] val) { + list.add(new PathDataNode(cmd, val)); + } + + private static class ExtractFloatResult { + // We need to return the position of the next separator and whether the + // next float starts with a '-' or a '.'. + private int mEndPosition; + private boolean mEndWithNegOrDot; + } + + /** + * Each PathDataNode represents one command in the "d" attribute of the svg file. An array of + * PathDataNode can represent the whole "d" attribute. + */ + private static class PathDataNode { + private char mType; + @NonNull + private float[] mParams; + + private PathDataNode(char type, @NonNull float[] params) { + mType = type; + mParams = params; + } + + public char getType() { + return mType; + } + + @NonNull + public float[] getParams() { + return mParams; + } + + private PathDataNode(@NonNull PathDataNode n) { + mType = n.mType; + mParams = Arrays.copyOf(n.mParams, n.mParams.length); + } + + /** + * Convert an array of PathDataNode to Path. + * + * @param node The source array of PathDataNode. + * @param path The target Path object. + */ + private static void nodesToPath(@NonNull PathDataNode[] node, @NonNull Path2D path) { + float[] current = new float[6]; + char previousCommand = 'm'; + //noinspection ForLoopReplaceableByForEach + for (int i = 0; i < node.length; i++) { + addCommand(path, current, previousCommand, node[i].mType, node[i].mParams); + previousCommand = node[i].mType; + } + } + + /** + * The current PathDataNode will be interpolated between the <code>nodeFrom</code> and + * <code>nodeTo</code> according to the <code>fraction</code>. + * + * @param nodeFrom The start value as a PathDataNode. + * @param nodeTo The end value as a PathDataNode + * @param fraction The fraction to interpolate. + */ + private void interpolatePathDataNode(@NonNull PathDataNode nodeFrom, + @NonNull PathDataNode nodeTo, float fraction) { + for (int i = 0; i < nodeFrom.mParams.length; i++) { + mParams[i] = nodeFrom.mParams[i] * (1 - fraction) + + nodeTo.mParams[i] * fraction; + } + } + + @SuppressWarnings("PointlessArithmeticExpression") + private static void addCommand(@NonNull Path2D path, float[] current, char cmd, + char lastCmd, @NonNull float[] val) { + + int incr = 2; + + float cx = current[0]; + float cy = current[1]; + float cpx = current[2]; + float cpy = current[3]; + float loopX = current[4]; + float loopY = current[5]; + + switch (cmd) { + case 'z': + case 'Z': + path.closePath(); + cx = loopX; + cy = loopY; + case 'm': + case 'M': + case 'l': + case 'L': + case 't': + case 'T': + incr = 2; + break; + case 'h': + case 'H': + case 'v': + case 'V': + incr = 1; + break; + case 'c': + case 'C': + incr = 6; + break; + case 's': + case 'S': + case 'q': + case 'Q': + incr = 4; + break; + case 'a': + case 'A': + incr = 7; + } + + for (int k = 0; k < val.length; k += incr) { + boolean reflectCtrl; + float tempReflectedX, tempReflectedY; + + switch (cmd) { + case 'm': + cx += val[k + 0]; + cy += val[k + 1]; + if (k > 0) { + // According to the spec, if a moveto is followed by multiple + // pairs of coordinates, the subsequent pairs are treated as + // implicit lineto commands. + path.lineTo(cx, cy); + } else { + path.moveTo(cx, cy); + loopX = cx; + loopY = cy; + } + break; + case 'M': + cx = val[k + 0]; + cy = val[k + 1]; + if (k > 0) { + // According to the spec, if a moveto is followed by multiple + // pairs of coordinates, the subsequent pairs are treated as + // implicit lineto commands. + path.lineTo(cx, cy); + } else { + path.moveTo(cx, cy); + loopX = cx; + loopY = cy; + } + break; + case 'l': + cx += val[k + 0]; + cy += val[k + 1]; + path.lineTo(cx, cy); + break; + case 'L': + cx = val[k + 0]; + cy = val[k + 1]; + path.lineTo(cx, cy); + break; + case 'z': + case 'Z': + path.closePath(); + cx = loopX; + cy = loopY; + break; + case 'h': + cx += val[k + 0]; + path.lineTo(cx, cy); + break; + case 'H': + path.lineTo(val[k + 0], cy); + cx = val[k + 0]; + break; + case 'v': + cy += val[k + 0]; + path.lineTo(cx, cy); + break; + case 'V': + path.lineTo(cx, val[k + 0]); + cy = val[k + 0]; + break; + case 'c': + path.curveTo(cx + val[k + 0], cy + val[k + 1], cx + val[k + 2], + cy + val[k + 3], cx + val[k + 4], cy + val[k + 5]); + cpx = cx + val[k + 2]; + cpy = cy + val[k + 3]; + cx += val[k + 4]; + cy += val[k + 5]; + break; + case 'C': + path.curveTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3], + val[k + 4], val[k + 5]); + cx = val[k + 4]; + cy = val[k + 5]; + cpx = val[k + 2]; + cpy = val[k + 3]; + break; + case 's': + reflectCtrl = (lastCmd == 'c' || lastCmd == 's' || lastCmd == 'C' || + lastCmd == 'S'); + path.curveTo(reflectCtrl ? 2 * cx - cpx : cx, reflectCtrl ? 2 + * cy - cpy : cy, cx + val[k + 0], cy + val[k + 1], cx + + val[k + 2], cy + val[k + 3]); + + cpx = cx + val[k + 0]; + cpy = cy + val[k + 1]; + cx += val[k + 2]; + cy += val[k + 3]; + break; + case 'S': + reflectCtrl = (lastCmd == 'c' || lastCmd == 's' || lastCmd == 'C' || + lastCmd == 'S'); + path.curveTo(reflectCtrl ? 2 * cx - cpx : cx, reflectCtrl ? 2 + * cy - cpy : cy, val[k + 0], val[k + 1], val[k + 2], + val[k + 3]); + cpx = (val[k + 0]); + cpy = (val[k + 1]); + cx = val[k + 2]; + cy = val[k + 3]; + break; + case 'q': + path.quadTo(cx + val[k + 0], cy + val[k + 1], cx + val[k + 2], + cy + val[k + 3]); + cpx = cx + val[k + 0]; + cpy = cy + val[k + 1]; + // Note that we have to update cpx first, since cx will be updated here. + cx += val[k + 2]; + cy += val[k + 3]; + break; + case 'Q': + path.quadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]); + cx = val[k + 2]; + cy = val[k + 3]; + cpx = val[k + 0]; + cpy = val[k + 1]; + break; + case 't': + reflectCtrl = (lastCmd == 'q' || lastCmd == 't' || lastCmd == 'Q' || + lastCmd == 'T'); + tempReflectedX = reflectCtrl ? 2 * cx - cpx : cx; + tempReflectedY = reflectCtrl ? 2 * cy - cpy : cy; + path.quadTo(tempReflectedX, tempReflectedY, cx + val[k + 0], + cy + val[k + 1]); + cpx = tempReflectedX; + cpy = tempReflectedY; + cx += val[k + 0]; + cy += val[k + 1]; + break; + case 'T': + reflectCtrl = (lastCmd == 'q' || lastCmd == 't' || lastCmd == 'Q' || + lastCmd == 'T'); + tempReflectedX = reflectCtrl ? 2 * cx - cpx : cx; + tempReflectedY = reflectCtrl ? 2 * cy - cpy : cy; + path.quadTo(tempReflectedX, tempReflectedY, val[k + 0], val[k + 1]); + cx = val[k + 0]; + cy = val[k + 1]; + cpx = tempReflectedX; + cpy = tempReflectedY; + break; + case 'a': + // (rx ry x-axis-rotation large-arc-flag sweep-flag x y) + drawArc(path, cx, cy, val[k + 5] + cx, val[k + 6] + cy, + val[k + 0], val[k + 1], val[k + 2], val[k + 3] != 0, + val[k + 4] != 0); + cx += val[k + 5]; + cy += val[k + 6]; + cpx = cx; + cpy = cy; + + break; + case 'A': + drawArc(path, cx, cy, val[k + 5], val[k + 6], val[k + 0], + val[k + 1], val[k + 2], val[k + 3] != 0, + val[k + 4] != 0); + cx = val[k + 5]; + cy = val[k + 6]; + cpx = cx; + cpy = cy; + break; + + } + lastCmd = cmd; + } + current[0] = cx; + current[1] = cy; + current[2] = cpx; + current[3] = cpy; + current[4] = loopX; + current[5] = loopY; + + } + + private static void drawArc(@NonNull Path2D p, float x0, float y0, float x1, + float y1, float a, float b, float theta, boolean isMoreThanHalf, + boolean isPositiveArc) { + + LOGGER.log(Level.FINE, "(" + x0 + "," + y0 + ")-(" + x1 + "," + y1 + + ") {" + a + " " + b + "}"); + /* Convert rotation angle from degrees to radians */ + double thetaD = theta * Math.PI / 180.0f; + /* Pre-compute rotation matrix entries */ + double cosTheta = Math.cos(thetaD); + double sinTheta = Math.sin(thetaD); + /* Transform (x0, y0) and (x1, y1) into unit space */ + /* using (inverse) rotation, followed by (inverse) scale */ + double x0p = (x0 * cosTheta + y0 * sinTheta) / a; + double y0p = (-x0 * sinTheta + y0 * cosTheta) / b; + double x1p = (x1 * cosTheta + y1 * sinTheta) / a; + double y1p = (-x1 * sinTheta + y1 * cosTheta) / b; + LOGGER.log(Level.FINE, "unit space (" + x0p + "," + y0p + ")-(" + x1p + + "," + y1p + ")"); + /* Compute differences and averages */ + double dx = x0p - x1p; + double dy = y0p - y1p; + double xm = (x0p + x1p) / 2; + double ym = (y0p + y1p) / 2; + /* Solve for intersecting unit circles */ + double dsq = dx * dx + dy * dy; + if (dsq == 0.0) { + LOGGER.log(Level.FINE, " Points are coincident"); + return; /* Points are coincident */ + } + double disc = 1.0 / dsq - 1.0 / 4.0; + if (disc < 0.0) { + LOGGER.log(Level.FINE, "Points are too far apart " + dsq); + float adjust = (float) (Math.sqrt(dsq) / 1.99999); + drawArc(p, x0, y0, x1, y1, a * adjust, b * adjust, theta, + isMoreThanHalf, isPositiveArc); + return; /* Points are too far apart */ + } + double s = Math.sqrt(disc); + double sdx = s * dx; + double sdy = s * dy; + double cx; + double cy; + if (isMoreThanHalf == isPositiveArc) { + cx = xm - sdy; + cy = ym + sdx; + } else { + cx = xm + sdy; + cy = ym - sdx; + } + + double eta0 = Math.atan2((y0p - cy), (x0p - cx)); + LOGGER.log(Level.FINE, "eta0 = Math.atan2( " + (y0p - cy) + " , " + + (x0p - cx) + ") = " + Math.toDegrees(eta0)); + + double eta1 = Math.atan2((y1p - cy), (x1p - cx)); + LOGGER.log(Level.FINE, "eta1 = Math.atan2( " + (y1p - cy) + " , " + + (x1p - cx) + ") = " + Math.toDegrees(eta1)); + double sweep = (eta1 - eta0); + if (isPositiveArc != (sweep >= 0)) { + if (sweep > 0) { + sweep -= 2 * Math.PI; + } else { + sweep += 2 * Math.PI; + } + } + + cx *= a; + cy *= b; + double tcx = cx; + cx = cx * cosTheta - cy * sinTheta; + cy = tcx * sinTheta + cy * cosTheta; + LOGGER.log( + Level.FINE, + "cx, cy, a, b, x0, y0, thetaD, eta0, sweep = " + cx + " , " + + cy + " , " + a + " , " + b + " , " + x0 + " , " + y0 + + " , " + Math.toDegrees(thetaD) + " , " + + Math.toDegrees(eta0) + " , " + Math.toDegrees(sweep)); + + arcToBezier(p, cx, cy, a, b, x0, y0, thetaD, eta0, sweep); + } + + /** + * Converts an arc to cubic Bezier segments and records them in p. + * + * @param p The target for the cubic Bezier segments + * @param cx The x coordinate center of the ellipse + * @param cy The y coordinate center of the ellipse + * @param a The radius of the ellipse in the horizontal direction + * @param b The radius of the ellipse in the vertical direction + * @param e1x E(eta1) x coordinate of the starting point of the arc + * @param e1y E(eta2) y coordinate of the starting point of the arc + * @param theta The angle that the ellipse bounding rectangle makes with the horizontal + * plane + * @param start The start angle of the arc on the ellipse + * @param sweep The angle (positive or negative) of the sweep of the arc on the ellipse + */ + private static void arcToBezier(@NonNull Path2D p, double cx, double cy, double a, + double b, double e1x, double e1y, double theta, double start, + double sweep) { + // Taken from equations at: + // http://spaceroots.org/documents/ellipse/node8.html + // and http://www.spaceroots.org/documents/ellipse/node22.html + // Maximum of 45 degrees per cubic Bezier segment + int numSegments = (int) Math.ceil(Math.abs(sweep * 4 / Math.PI)); + + + double eta1 = start; + double cosTheta = Math.cos(theta); + double sinTheta = Math.sin(theta); + double cosEta1 = Math.cos(eta1); + double sinEta1 = Math.sin(eta1); + double ep1x = (-a * cosTheta * sinEta1) - (b * sinTheta * cosEta1); + double ep1y = (-a * sinTheta * sinEta1) + (b * cosTheta * cosEta1); + + double anglePerSegment = sweep / numSegments; + for (int i = 0; i < numSegments; i++) { + double eta2 = eta1 + anglePerSegment; + double sinEta2 = Math.sin(eta2); + double cosEta2 = Math.cos(eta2); + double e2x = cx + (a * cosTheta * cosEta2) + - (b * sinTheta * sinEta2); + double e2y = cy + (a * sinTheta * cosEta2) + + (b * cosTheta * sinEta2); + double ep2x = -a * cosTheta * sinEta2 - b * sinTheta * cosEta2; + double ep2y = -a * sinTheta * sinEta2 + b * cosTheta * cosEta2; + double tanDiff2 = Math.tan((eta2 - eta1) / 2); + double alpha = Math.sin(eta2 - eta1) + * (Math.sqrt(4 + (3 * tanDiff2 * tanDiff2)) - 1) / 3; + double q1x = e1x + alpha * ep1x; + double q1y = e1y + alpha * ep1y; + double q2x = e2x - alpha * ep2x; + double q2y = e2y - alpha * ep2y; + + p.curveTo((float) q1x, (float) q1y, (float) q2x, (float) q2y, + (float) e2x, (float) e2y); + eta1 = eta2; + e1x = e2x; + e1y = e2y; + ep1x = ep2x; + ep1y = ep2y; + } + } + } +} diff --git a/tools/layoutlib/bridge/src/android/widget/TimePickerClockDelegate_Delegate.java b/tools/layoutlib/bridge/src/android/widget/TimePickerClockDelegate_Delegate.java deleted file mode 100644 index 1bd98301dc42..000000000000 --- a/tools/layoutlib/bridge/src/android/widget/TimePickerClockDelegate_Delegate.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2014 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.widget; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.view.KeyEvent; - -/** - * Delegate used to provide new implementation of few methods in {@link TimePickerClockDelegate}. - */ -public class TimePickerClockDelegate_Delegate { - - // Copied from TimePickerClockDelegate. - private static final int AM = 0; - private static final int PM = 1; - - @LayoutlibDelegate - static int getAmOrPmKeyCode(TimePickerClockDelegate tpcd, int amOrPm) { - // We don't care about locales here. - if (amOrPm == AM) { - return KeyEvent.KEYCODE_A; - } else if (amOrPm == PM) { - return KeyEvent.KEYCODE_P; - } else { - assert false : "amOrPm value in TimePickerSpinnerDelegate can only be 0 or 1"; - return -1; - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterHelper.java index 8c60bae4f11e..c0ca1d5916e9 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterHelper.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterHelper.java @@ -36,9 +36,9 @@ import android.widget.TextView; /** * A Helper class to do fake data binding in {@link AdapterView} objects. */ -@SuppressWarnings("deprecation") public class AdapterHelper { + @SuppressWarnings("deprecation") static Pair<View, Boolean> getView(AdapterItem item, AdapterItem parentItem, ViewGroup parent, LayoutlibCallback callback, ResourceReference adapterRef, boolean skipCallbackParser) { // we don't care about recycling here because we never scroll. diff --git a/tools/layoutlib/bridge/src/libcore/util/NativeAllocationRegistry_Delegate.java b/tools/layoutlib/bridge/src/libcore/util/NativeAllocationRegistry_Delegate.java new file mode 100644 index 000000000000..6246ec1b8661 --- /dev/null +++ b/tools/layoutlib/bridge/src/libcore/util/NativeAllocationRegistry_Delegate.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2016 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.util; + +import com.android.layoutlib.bridge.impl.DelegateManager; +import com.android.tools.layoutlib.annotations.LayoutlibDelegate; + +/** + * Delegate implementing the native methods of {@link NativeAllocationRegistry} + * + * Through the layoutlib_create tool, the original native methods of NativeAllocationRegistry 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 NativeAllocationRegistry class. + * + * @see DelegateManager + */ +public class NativeAllocationRegistry_Delegate { + + // ---- delegate manager ---- + private static final DelegateManager<NativeAllocationRegistry_Delegate> sManager = + new DelegateManager<>(NativeAllocationRegistry_Delegate.class); + + private final FreeFunction mFinalizer; + + private NativeAllocationRegistry_Delegate(FreeFunction finalizer) { + mFinalizer = finalizer; + } + + /** + * The result of this method should be cached by the class and reused. + */ + public static long createFinalizer(FreeFunction finalizer) { + return sManager.addNewDelegate(new NativeAllocationRegistry_Delegate(finalizer)); + } + + @LayoutlibDelegate + /*package*/ static void applyFreeFunction(long freeFunction, long nativePtr) { + NativeAllocationRegistry_Delegate delegate = sManager.getDelegate(freeFunction); + if (delegate != null) { + delegate.mFinalizer.free(nativePtr); + } + } + + public interface FreeFunction { + void free(long nativePtr); + } +} diff --git a/tools/layoutlib/bridge/tests/Android.mk b/tools/layoutlib/bridge/tests/Android.mk index 5eef24adbdef..8a81d0b684db 100644 --- a/tools/layoutlib/bridge/tests/Android.mk +++ b/tools/layoutlib/bridge/tests/Android.mk @@ -19,7 +19,6 @@ include $(CLEAR_VARS) # Only compile source java files in this lib. LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_JAVA_RESOURCE_DIRS := res -LOCAL_JAVACFLAGS := -source 6 -target 6 LOCAL_MODULE := layoutlib-tests LOCAL_MODULE_TAGS := optional diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/ImageUtils.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/ImageUtils.java index 16911bdd7c2a..8f9fa8a2bcf6 100644 --- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/ImageUtils.java +++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/ImageUtils.java @@ -75,8 +75,12 @@ public class ImageUtils { } } else { - BufferedImage goldenImage = ImageIO.read(is); - assertImageSimilar(relativePath, goldenImage, thumbnail, MAX_PERCENT_DIFFERENCE); + try { + BufferedImage goldenImage = ImageIO.read(is); + assertImageSimilar(relativePath, goldenImage, thumbnail, MAX_PERCENT_DIFFERENCE); + } finally { + is.close(); + } } } diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AbstractClassAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AbstractClassAdapter.java index 758bd48e6067..01c940ad665c 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AbstractClassAdapter.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AbstractClassAdapter.java @@ -176,17 +176,6 @@ public abstract class AbstractClassAdapter extends ClassVisitor { } } - /* Java 7 verifies the StackMapTable of a class if its version number is greater than 50.0. - * However, the check is disabled if the class version number is 50.0 or less. Generation - * of the StackMapTable requires a rewrite using the tree API of ASM. As a workaround, - * we rewrite the version number of the class to be 50.0 - * - * http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6693236 - */ - if (version > 50) { - version = 50; - } - super.visit(version, access, name, signature, superName, interfaces); } diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java index d106592118c8..189ecdc4e96a 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java @@ -144,11 +144,8 @@ public final class CreateInfo implements ICreateInfo { InjectMethodRunnable.class, InjectMethodRunnables.class, /* Java package classes */ - AutoCloseable.class, - Objects.class, IntegralToString.class, UnsafeByteSequence.class, - Charsets.class, System_Delegate.class, LinkedHashMap_Delegate.class, }; @@ -169,6 +166,7 @@ public final class CreateInfo implements ICreateInfo { "android.graphics.BitmapFactory#setDensityFromOptions", "android.graphics.drawable.GradientDrawable#buildRing", "android.graphics.Typeface#getSystemFontConfigLocation", + "android.graphics.Typeface#makeFamilyFromParsed", "android.os.Handler#sendMessageAtTime", "android.os.HandlerThread#run", "android.preference.Preference#getView", @@ -188,6 +186,7 @@ public final class CreateInfo implements ICreateInfo { "android.view.WindowManagerGlobal#getWindowManagerService", "android.view.inputmethod.InputMethodManager#getInstance", "android.view.MenuInflater#registerMenu", + "android.view.RenderNode#getMatrix", "android.view.RenderNode#nCreate", "android.view.RenderNode#nDestroyRenderNode", "android.view.RenderNode#nSetElevation", @@ -200,7 +199,6 @@ public final class CreateInfo implements ICreateInfo { "android.view.RenderNode#nGetTranslationZ", "android.view.RenderNode#nSetRotation", "android.view.RenderNode#nGetRotation", - "android.view.RenderNode#getMatrix", "android.view.RenderNode#nSetLeft", "android.view.RenderNode#nSetTop", "android.view.RenderNode#nSetRight", @@ -216,7 +214,6 @@ public final class CreateInfo implements ICreateInfo { "android.view.RenderNode#nGetScaleY", "android.view.RenderNode#nIsPivotExplicitlySet", "android.view.ViewGroup#drawChild", - "android.widget.TimePickerClockDelegate#getAmOrPmKeyCode", "com.android.internal.view.menu.MenuBuilder#createNewMenuItem", "com.android.internal.util.XmlUtils#convertValueToInt", "com.android.internal.textservice.ITextServicesManager$Stub#asInterface", @@ -224,6 +221,7 @@ public final class CreateInfo implements ICreateInfo { "libcore.io.MemoryMappedFile#mmapRO", "libcore.io.MemoryMappedFile#close", "libcore.io.MemoryMappedFile#bigEndianIterator", + "libcore.util.NativeAllocationRegistry#applyFreeFunction", }; /** @@ -274,6 +272,7 @@ public final class CreateInfo implements ICreateInfo { "android.os.SystemProperties", "android.text.AndroidBidi", "android.text.StaticLayout", + "android.util.PathParser", "android.view.Display", "libcore.icu.ICU", }; @@ -306,12 +305,9 @@ public final class CreateInfo implements ICreateInfo { */ private final static String[] JAVA_PKG_CLASSES = new String[] { - "java.lang.AutoCloseable", "com.android.tools.layoutlib.java.AutoCloseable", - "java.util.Objects", "com.android.tools.layoutlib.java.Objects", - "java.nio.charset.Charsets", "com.android.tools.layoutlib.java.Charsets", + "java.nio.charset.Charsets", "java.nio.charset.StandardCharsets", "java.lang.IntegralToString", "com.android.tools.layoutlib.java.IntegralToString", "java.lang.UnsafeByteSequence", "com.android.tools.layoutlib.java.UnsafeByteSequence", - "java.nio.charset.StandardCharsets", "com.android.tools.layoutlib.java.Charsets", }; private final static String[] EXCLUDED_CLASSES = diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java index b5ab73855189..4ba7237d7991 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java @@ -103,6 +103,7 @@ class StubMethodAdapter extends MethodVisitor { mParentVisitor.visitInsn(Opcodes.ICONST_1); mParentVisitor.visitInsn(Opcodes.IRETURN); mParentVisitor.visitLabel(l1); + mParentVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null); mParentVisitor.visitInsn(Opcodes.ICONST_0); break; case Type.CHAR: |