diff options
author | Diego Perez <diegoperez@google.com> | 2017-04-21 14:20:16 +0100 |
---|---|---|
committer | Diego Perez <diegoperez@google.com> | 2017-05-10 12:34:29 +0100 |
commit | 4493b7c429e45ddbdeaefdbf5b8536dcedb5d66c (patch) | |
tree | 83be88f7c30f7e4306e823e717452ae250641bdc /tools/layoutlib/bridge/src | |
parent | 13f6a914c2d2b76f3e703b4c5798674627e28116 (diff) |
Removing layout from frameworks/base
The directory is being moved to its own project in frameworks/layoutlib
Bug: 36889565
Test: Built manually
Change-Id: I69a1a826d0bac8ede1f9a337c9c1d930bbcd04f3
Diffstat (limited to 'tools/layoutlib/bridge/src')
175 files changed, 0 insertions, 40267 deletions
diff --git a/tools/layoutlib/bridge/src/android/animation/AnimationThread.java b/tools/layoutlib/bridge/src/android/animation/AnimationThread.java deleted file mode 100644 index ce2aec790119..000000000000 --- a/tools/layoutlib/bridge/src/android/animation/AnimationThread.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.animation; - -import com.android.ide.common.rendering.api.IAnimationListener; -import com.android.ide.common.rendering.api.RenderSession; -import com.android.ide.common.rendering.api.Result; -import com.android.ide.common.rendering.api.Result.Status; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.impl.RenderSessionImpl; - -import android.os.Handler; -import android.os.Handler_Delegate; -import android.os.Message; - -import java.util.PriorityQueue; -import java.util.Queue; - -/** - * Abstract animation thread. - * <p/> - * This does not actually start an animation, instead it fakes a looper that will play whatever - * animation is sending messages to its own {@link Handler}. - * <p/> - * Classes should implement {@link #preAnimation()} and {@link #postAnimation()}. - * <p/> - * If {@link #preAnimation()} does not start an animation somehow then the thread doesn't do - * anything. - * - */ -public abstract class AnimationThread extends Thread { - - private static class MessageBundle implements Comparable<MessageBundle> { - final Handler mTarget; - final Message mMessage; - final long mUptimeMillis; - - MessageBundle(Handler target, Message message, long uptimeMillis) { - mTarget = target; - mMessage = message; - mUptimeMillis = uptimeMillis; - } - - @Override - public int compareTo(MessageBundle bundle) { - if (mUptimeMillis < bundle.mUptimeMillis) { - return -1; - } - return 1; - } - } - - private final RenderSessionImpl mSession; - - private Queue<MessageBundle> mQueue = new PriorityQueue<MessageBundle>(); - private final IAnimationListener mListener; - - public AnimationThread(RenderSessionImpl scene, String threadName, - IAnimationListener listener) { - super(threadName); - mSession = scene; - mListener = listener; - } - - public abstract Result preAnimation(); - public abstract void postAnimation(); - - @Override - public void run() { - Bridge.prepareThread(); - try { - /* FIXME: The ANIMATION_FRAME message no longer exists. Instead, the - * animation timing loop is completely based on a Choreographer objects - * that schedules animation and drawing frames. The animation handler is - * no longer even a handler; it is just a Runnable enqueued on the Choreographer. - Handler_Delegate.setCallback(new IHandlerCallback() { - @Override - public void sendMessageAtTime(Handler handler, Message msg, long uptimeMillis) { - if (msg.what == ValueAnimator.ANIMATION_START || - msg.what == ValueAnimator.ANIMATION_FRAME) { - mQueue.add(new MessageBundle(handler, msg, uptimeMillis)); - } else { - // just ignore. - } - } - }); - */ - - // call out to the pre-animation work, which should start an animation or more. - Result result = preAnimation(); - if (result.isSuccess() == false) { - mListener.done(result); - } - - // loop the animation - RenderSession session = mSession.getSession(); - do { - // check early. - if (mListener.isCanceled()) { - break; - } - - // get the next message. - MessageBundle bundle = mQueue.poll(); - if (bundle == null) { - break; - } - - // sleep enough for this bundle to be on time - long currentTime = System.currentTimeMillis(); - if (currentTime < bundle.mUptimeMillis) { - try { - sleep(bundle.mUptimeMillis - currentTime); - } catch (InterruptedException e) { - // FIXME log/do something/sleep again? - e.printStackTrace(); - } - } - - // check after sleeping. - if (mListener.isCanceled()) { - break; - } - - // ready to do the work, acquire the scene. - result = mSession.acquire(250); - if (result.isSuccess() == false) { - mListener.done(result); - return; - } - - // process the bundle. If the animation is not finished, this will enqueue - // the next message, so mQueue will have another one. - try { - // check after acquiring in case it took a while. - if (mListener.isCanceled()) { - break; - } - - bundle.mTarget.handleMessage(bundle.mMessage); - if (mSession.render(false /*freshRender*/).isSuccess()) { - mListener.onNewFrame(session); - } - } finally { - mSession.release(); - } - } while (mListener.isCanceled() == false && mQueue.size() > 0); - - mListener.done(Status.SUCCESS.createResult()); - - } catch (Throwable throwable) { - // can't use Bridge.getLog() as the exception might be thrown outside - // of an acquire/release block. - mListener.done(Status.ERROR_UNKNOWN.createResult("Error playing animation", throwable)); - - } finally { - postAnimation(); - Handler_Delegate.setCallback(null); - Bridge.cleanupThread(); - } - } -} diff --git a/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java b/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java deleted file mode 100644 index 28a489ad6ed7..000000000000 --- a/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.animation; - -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -/** - * Delegate implementing the native methods of android.animation.PropertyValuesHolder - * - * Through the layoutlib_create tool, the original native methods of PropertyValuesHolder have been - * replaced by calls to methods of the same name in this delegate class. - * - * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager} - * around to map int to instance of the delegate. - * - * The main goal of this class' methods are to provide a native way to access setters and getters - * on some object. We override these methods to use reflection since the original reflection - * implementation of the PropertyValuesHolder won't be able to access protected methods. - * - */ -/*package*/ -@SuppressWarnings("unused") -class PropertyValuesHolder_Delegate { - // This code is copied from android.animation.PropertyValuesHolder and must be kept in sync - // We try several different types when searching for appropriate setter/getter functions. - // The caller may have supplied values in a type that does not match the setter/getter - // functions (such as the integers 0 and 1 to represent floating point values for alpha). - // Also, the use of generics in constructors means that we end up with the Object versions - // of primitive types (Float vs. float). But most likely, the setter/getter functions - // will take primitive types instead. - // So we supply an ordered array of other types to try before giving up. - private static Class[] FLOAT_VARIANTS = {float.class, Float.class, double.class, int.class, - Double.class, Integer.class}; - private static Class[] INTEGER_VARIANTS = {int.class, Integer.class, float.class, double.class, - Float.class, Double.class}; - - private static final Object sMethodIndexLock = new Object(); - private static final Map<Long, Method> ID_TO_METHOD = new HashMap<Long, Method>(); - private static final Map<String, Long> METHOD_NAME_TO_ID = new HashMap<String, Long>(); - private static long sNextId = 1; - - private static long registerMethod(Class<?> targetClass, String methodName, Class[] types, - int nArgs) { - // Encode the number of arguments in the method name - String methodIndexName = String.format("%1$s.%2$s#%3$d", targetClass.getSimpleName(), - methodName, nArgs); - synchronized (sMethodIndexLock) { - Long methodId = METHOD_NAME_TO_ID.get(methodIndexName); - - if (methodId != null) { - // The method was already registered - return methodId; - } - - Class[] args = new Class[nArgs]; - Method method = null; - for (Class typeVariant : types) { - for (int i = 0; i < nArgs; i++) { - args[i] = typeVariant; - } - try { - method = targetClass.getDeclaredMethod(methodName, args); - } catch (NoSuchMethodException ignore) { - } - } - - if (method != null) { - methodId = sNextId++; - ID_TO_METHOD.put(methodId, method); - METHOD_NAME_TO_ID.put(methodIndexName, methodId); - - return methodId; - } - } - - // Method not found - return 0; - } - - private static void callMethod(Object target, long methodID, Object... args) { - Method method = ID_TO_METHOD.get(methodID); - assert method != null; - - try { - method.setAccessible(true); - method.invoke(target, args); - } catch (IllegalAccessException e) { - Bridge.getLog().error(null, "Unable to update property during animation", e, null); - } catch (InvocationTargetException e) { - Bridge.getLog().error(null, "Unable to update property during animation", e, null); - } - } - - @LayoutlibDelegate - /*package*/ static long nGetIntMethod(Class<?> targetClass, String methodName) { - return nGetMultipleIntMethod(targetClass, methodName, 1); - } - - @LayoutlibDelegate - /*package*/ static long nGetFloatMethod(Class<?> targetClass, String methodName) { - return nGetMultipleFloatMethod(targetClass, methodName, 1); - } - - @LayoutlibDelegate - /*package*/ static long nGetMultipleIntMethod(Class<?> targetClass, String methodName, - int numParams) { - return registerMethod(targetClass, methodName, INTEGER_VARIANTS, numParams); - } - - @LayoutlibDelegate - /*package*/ static long nGetMultipleFloatMethod(Class<?> targetClass, String methodName, - int numParams) { - return registerMethod(targetClass, methodName, FLOAT_VARIANTS, numParams); - } - - @LayoutlibDelegate - /*package*/ static void nCallIntMethod(Object target, long methodID, int arg) { - callMethod(target, methodID, arg); - } - - @LayoutlibDelegate - /*package*/ static void nCallFloatMethod(Object target, long methodID, float arg) { - callMethod(target, methodID, arg); - } - - @LayoutlibDelegate - /*package*/ static void nCallTwoIntMethod(Object target, long methodID, int arg1, - int arg2) { - callMethod(target, methodID, arg1, arg2); - } - - @LayoutlibDelegate - /*package*/ static void nCallFourIntMethod(Object target, long methodID, int arg1, - int arg2, int arg3, int arg4) { - callMethod(target, methodID, arg1, arg2, arg3, arg4); - } - - @LayoutlibDelegate - /*package*/ static void nCallMultipleIntMethod(Object target, long methodID, - int[] args) { - assert args != null; - - // Box parameters - Object[] params = new Object[args.length]; - for (int i = 0; i < args.length; i++) { - params[i] = args; - } - callMethod(target, methodID, params); - } - - @LayoutlibDelegate - /*package*/ static void nCallTwoFloatMethod(Object target, long methodID, float arg1, - float arg2) { - callMethod(target, methodID, arg1, arg2); - } - - @LayoutlibDelegate - /*package*/ static void nCallFourFloatMethod(Object target, long methodID, float arg1, - float arg2, float arg3, float arg4) { - callMethod(target, methodID, arg1, arg2, arg3, arg4); - } - - @LayoutlibDelegate - /*package*/ static void nCallMultipleFloatMethod(Object target, long methodID, - float[] args) { - assert args != null; - - // Box parameters - Object[] params = new Object[args.length]; - for (int i = 0; i < args.length; i++) { - params[i] = args; - } - callMethod(target, methodID, params); - } -} diff --git a/tools/layoutlib/bridge/src/android/app/Fragment_Delegate.java b/tools/layoutlib/bridge/src/android/app/Fragment_Delegate.java deleted file mode 100644 index f7654ce231b2..000000000000 --- a/tools/layoutlib/bridge/src/android/app/Fragment_Delegate.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.app; - -import com.android.ide.common.rendering.api.LayoutlibCallback; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.content.Context; -import android.os.Bundle; - -/** - * Delegate used to provide new implementation of a select few methods of {@link Fragment} - * - * Through the layoutlib_create tool, the original methods of Fragment have been replaced - * by calls to methods of the same name in this delegate class. - * - * The methods being re-implemented are the ones responsible for instantiating Fragment objects. - * Because the classes of these objects are found in the project, these methods need access to - * {@link LayoutlibCallback} object. They are however static methods, so the callback is set - * before the inflation through {@link #setLayoutlibCallback(LayoutlibCallback)}. - */ -public class Fragment_Delegate { - - private static LayoutlibCallback sLayoutlibCallback; - - /** - * Sets the current {@link LayoutlibCallback} to be used to instantiate classes coming - * from the project being rendered. - */ - public static void setLayoutlibCallback(LayoutlibCallback layoutlibCallback) { - sLayoutlibCallback = layoutlibCallback; - } - - /** - * Like {@link #instantiate(Context, String, Bundle)} but with a null - * argument Bundle. - */ - @LayoutlibDelegate - /*package*/ static Fragment instantiate(Context context, String fname) { - return instantiate(context, fname, null); - } - - /** - * Create a new instance of a Fragment with the given class name. This is - * the same as calling its empty constructor. - * - * @param context The calling context being used to instantiate the fragment. - * This is currently just used to get its ClassLoader. - * @param fname The class name of the fragment to instantiate. - * @param args Bundle of arguments to supply to the fragment, which it - * can retrieve with {@link Fragment#getArguments()}. May be null. - * @return Returns a new fragment instance. - * @throws Fragment.InstantiationException If there is a failure in instantiating - * the given fragment class. This is a runtime exception; it is not - * normally expected to happen. - */ - @LayoutlibDelegate - /*package*/ static Fragment instantiate(Context context, String fname, Bundle args) { - try { - if (sLayoutlibCallback != null) { - Fragment f = (Fragment) sLayoutlibCallback.loadView(fname, - new Class[0], new Object[0]); - - if (args != null) { - args.setClassLoader(f.getClass().getClassLoader()); - f.mArguments = args; - } - return f; - } - - return null; - } catch (ClassNotFoundException e) { - throw new Fragment.InstantiationException("Unable to instantiate fragment " + fname - + ": make sure class name exists, is public, and has an" - + " empty constructor that is public", e); - } catch (java.lang.InstantiationException e) { - throw new Fragment.InstantiationException("Unable to instantiate fragment " + fname - + ": make sure class name exists, is public, and has an" - + " empty constructor that is public", e); - } catch (IllegalAccessException e) { - throw new Fragment.InstantiationException("Unable to instantiate fragment " + fname - + ": make sure class name exists, is public, and has an" - + " empty constructor that is public", e); - } catch (Exception e) { - throw new Fragment.InstantiationException("Unable to instantiate fragment " + fname - + ": make sure class name exists, is public, and has an" - + " empty constructor that is public", e); - } - } -} diff --git a/tools/layoutlib/bridge/src/android/app/SystemServiceRegistry_Accessor.java b/tools/layoutlib/bridge/src/android/app/SystemServiceRegistry_Accessor.java deleted file mode 100644 index 591aee07aa3f..000000000000 --- a/tools/layoutlib/bridge/src/android/app/SystemServiceRegistry_Accessor.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2017 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.app; - -/** - * Class to allow accessing {@link SystemServiceRegistry#getSystemServiceName} - */ -public class SystemServiceRegistry_Accessor { - /** - * Gets the name of the system-level service that is represented by the specified class. - */ - public static String getSystemServiceName(Class<?> serviceClass) { - return SystemServiceRegistry.getSystemServiceName(serviceClass); - } -} diff --git a/tools/layoutlib/bridge/src/android/content/res/AssetManager_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/AssetManager_Delegate.java deleted file mode 100644 index b4d5288bc925..000000000000 --- a/tools/layoutlib/bridge/src/android/content/res/AssetManager_Delegate.java +++ /dev/null @@ -1,47 +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.content.res; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.util.SparseArray; - -/** - * Delegate used to provide implementation of a select few native methods of {@link AssetManager} - * <p/> - * Through the layoutlib_create tool, the original native methods of AssetManager have been replaced - * by calls to methods of the same name in this delegate class. - * - */ -public class AssetManager_Delegate { - - @LayoutlibDelegate - /*package*/ static long newTheme(AssetManager manager) { - return Resources_Theme_Delegate.getDelegateManager() - .addNewDelegate(new Resources_Theme_Delegate()); - } - - @LayoutlibDelegate - /*package*/ static void deleteTheme(AssetManager manager, long theme) { - Resources_Theme_Delegate.getDelegateManager().removeJavaReferenceFor(theme); - } - - @LayoutlibDelegate - /*package*/ static SparseArray<String> getAssignedPackageIdentifiers(AssetManager manager) { - return new SparseArray<>(); - } -} diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeAssetManager.java b/tools/layoutlib/bridge/src/android/content/res/BridgeAssetManager.java deleted file mode 100644 index 2691e5640ff0..000000000000 --- a/tools/layoutlib/bridge/src/android/content/res/BridgeAssetManager.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.content.res; - -import com.android.ide.common.rendering.api.AssetRepository; -import com.android.layoutlib.bridge.Bridge; - -public class BridgeAssetManager extends AssetManager { - - private AssetRepository mAssetRepository; - - /** - * This initializes the static field {@link AssetManager#sSystem} which is used - * by methods who get a global asset manager using {@link AssetManager#getSystem()}. - * <p/> - * They will end up using our bridge asset manager. - * <p/> - * {@link Bridge} calls this method after setting up a new bridge. - */ - public static AssetManager initSystem() { - if (!(AssetManager.sSystem instanceof BridgeAssetManager)) { - // Note that AssetManager() creates a system AssetManager and we override it - // with our BridgeAssetManager. - AssetManager.sSystem = new BridgeAssetManager(); - AssetManager.sSystem.makeStringBlocks(null); - } - return AssetManager.sSystem; - } - - /** - * Clears the static {@link AssetManager#sSystem} to make sure we don't leave objects - * around that would prevent us from unloading the library. - */ - public static void clearSystem() { - AssetManager.sSystem = null; - } - - public void setAssetRepository(AssetRepository assetRepository) { - mAssetRepository = assetRepository; - } - - public AssetRepository getAssetRepository() { - return mAssetRepository; - } - - public BridgeAssetManager() { - } -} diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java deleted file mode 100644 index b5996afd7985..000000000000 --- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java +++ /dev/null @@ -1,1011 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.content.res; - -import com.android.ide.common.rendering.api.ArrayResourceValue; -import com.android.ide.common.rendering.api.AttrResourceValue; -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.ide.common.rendering.api.StyleResourceValue; -import com.android.internal.util.XmlUtils; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.impl.ResourceHelper; -import com.android.resources.ResourceType; - -import android.annotation.Nullable; -import android.content.res.Resources.NotFoundException; -import android.content.res.Resources.Theme; -import android.graphics.Typeface; -import android.graphics.drawable.Drawable; -import android.util.DisplayMetrics; -import android.util.TypedValue; -import android.view.LayoutInflater_Delegate; -import android.view.ViewGroup.LayoutParams; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Map; - -import static android.util.TypedValue.TYPE_ATTRIBUTE; -import static android.util.TypedValue.TYPE_DIMENSION; -import static android.util.TypedValue.TYPE_FLOAT; -import static android.util.TypedValue.TYPE_INT_BOOLEAN; -import static android.util.TypedValue.TYPE_INT_COLOR_ARGB4; -import static android.util.TypedValue.TYPE_INT_COLOR_ARGB8; -import static android.util.TypedValue.TYPE_INT_COLOR_RGB4; -import static android.util.TypedValue.TYPE_INT_COLOR_RGB8; -import static android.util.TypedValue.TYPE_INT_DEC; -import static android.util.TypedValue.TYPE_INT_HEX; -import static android.util.TypedValue.TYPE_NULL; -import static android.util.TypedValue.TYPE_REFERENCE; -import static android.util.TypedValue.TYPE_STRING; -import static com.android.SdkConstants.PREFIX_RESOURCE_REF; -import static com.android.SdkConstants.PREFIX_THEME_REF; -import static com.android.ide.common.rendering.api.RenderResources.REFERENCE_EMPTY; -import static com.android.ide.common.rendering.api.RenderResources.REFERENCE_NULL; -import static com.android.ide.common.rendering.api.RenderResources.REFERENCE_UNDEFINED; - -/** - * Custom implementation of TypedArray to handle non compiled resources. - */ -public final class BridgeTypedArray extends TypedArray { - - private final Resources mBridgeResources; - private final BridgeContext mContext; - private final boolean mPlatformFile; - - private final ResourceValue[] mResourceData; - private final String[] mNames; - private final boolean[] mIsFramework; - - // Contains ids that are @empty. We still store null in mResourceData for that index, since we - // want to save on the check against empty, each time a resource value is requested. - @Nullable - private int[] mEmptyIds; - - public BridgeTypedArray(Resources resources, BridgeContext context, int len, - boolean platformFile) { - super(resources); - mBridgeResources = resources; - mContext = context; - mPlatformFile = platformFile; - mResourceData = new ResourceValue[len]; - mNames = new String[len]; - mIsFramework = new boolean[len]; - } - - /** - * A bridge-specific method that sets a value in the type array - * @param index the index of the value in the TypedArray - * @param name the name of the attribute - * @param isFramework whether the attribute is in the android namespace. - * @param value the value of the attribute - */ - public void bridgeSetValue(int index, String name, boolean isFramework, ResourceValue value) { - mResourceData[index] = value; - mNames[index] = name; - mIsFramework[index] = isFramework; - } - - /** - * Seals the array after all calls to - * {@link #bridgeSetValue(int, String, boolean, ResourceValue)} have been done. - * <p/>This allows to compute the list of non default values, permitting - * {@link #getIndexCount()} to return the proper value. - */ - public void sealArray() { - // fills TypedArray.mIndices which is used to implement getIndexCount/getIndexAt - // first count the array size - int count = 0; - ArrayList<Integer> emptyIds = null; - for (int i = 0; i < mResourceData.length; i++) { - ResourceValue data = mResourceData[i]; - if (data != null) { - String dataValue = data.getValue(); - if (REFERENCE_NULL.equals(dataValue) || REFERENCE_UNDEFINED.equals(dataValue)) { - mResourceData[i] = null; - } else if (REFERENCE_EMPTY.equals(dataValue)) { - mResourceData[i] = null; - if (emptyIds == null) { - emptyIds = new ArrayList<Integer>(4); - } - emptyIds.add(i); - } else { - count++; - } - } - } - - if (emptyIds != null) { - mEmptyIds = new int[emptyIds.size()]; - for (int i = 0; i < emptyIds.size(); i++) { - mEmptyIds[i] = emptyIds.get(i); - } - } - - // allocate the table with an extra to store the size - mIndices = new int[count+1]; - mIndices[0] = count; - - // fill the array with the indices. - int index = 1; - for (int i = 0 ; i < mResourceData.length ; i++) { - if (mResourceData[i] != null) { - mIndices[index++] = i; - } - } - } - - /** - * Set the theme to be used for inflating drawables. - */ - public void setTheme(Theme theme) { - mTheme = theme; - } - - /** - * Return the number of values in this array. - */ - @Override - public int length() { - return mResourceData.length; - } - - /** - * Return the Resources object this array was loaded from. - */ - @Override - public Resources getResources() { - return mBridgeResources; - } - - /** - * Retrieve the styled string value for the attribute at <var>index</var>. - * - * @param index Index of attribute to retrieve. - * - * @return CharSequence holding string data. May be styled. Returns - * null if the attribute is not defined. - */ - @Override - public CharSequence getText(int index) { - // FIXME: handle styled strings! - return getString(index); - } - - /** - * Retrieve the string value for the attribute at <var>index</var>. - * - * @param index Index of attribute to retrieve. - * - * @return String holding string data. Any styling information is - * removed. Returns null if the attribute is not defined. - */ - @Override - public String getString(int index) { - if (!hasValue(index)) { - return null; - } - // As unfortunate as it is, it's possible to use enums with all attribute formats, - // not just integers/enums. So, we need to search the enums always. In case - // enums are used, the returned value is an integer. - Integer v = resolveEnumAttribute(index); - return v == null ? mResourceData[index].getValue() : String.valueOf((int) v); - } - - /** - * Retrieve the boolean value for the attribute at <var>index</var>. - * - * @param index Index of attribute to retrieve. - * @param defValue Value to return if the attribute is not defined. - * - * @return Attribute boolean value, or defValue if not defined. - */ - @Override - public boolean getBoolean(int index, boolean defValue) { - String s = getString(index); - return s == null ? defValue : XmlUtils.convertValueToBoolean(s, defValue); - - } - - /** - * Retrieve the integer value for the attribute at <var>index</var>. - * - * @param index Index of attribute to retrieve. - * @param defValue Value to return if the attribute is not defined. - * - * @return Attribute int value, or defValue if not defined. - */ - @Override - public int getInt(int index, int defValue) { - String s = getString(index); - try { - return convertValueToInt(s, defValue); - } catch (NumberFormatException e) { - Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT, - String.format("\"%1$s\" in attribute \"%2$s\" is not a valid integer", - s, mNames[index]), - null); - } - return defValue; - } - - /** - * Retrieve the float value for the attribute at <var>index</var>. - * - * @param index Index of attribute to retrieve. - * - * @return Attribute float value, or defValue if not defined.. - */ - @Override - public float getFloat(int index, float defValue) { - String s = getString(index); - try { - if (s != null) { - return Float.parseFloat(s); - } - } catch (NumberFormatException e) { - Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT, - String.format("\"%1$s\" in attribute \"%2$s\" cannot be converted to float.", - s, mNames[index]), - null); - } - return defValue; - } - - /** - * Retrieve the color value for the attribute at <var>index</var>. If - * the attribute references a color resource holding a complex - * {@link android.content.res.ColorStateList}, then the default color from - * the set is returned. - * - * @param index Index of attribute to retrieve. - * @param defValue Value to return if the attribute is not defined or - * not a resource. - * - * @return Attribute color value, or defValue if not defined. - */ - @Override - public int getColor(int index, int defValue) { - if (index < 0 || index >= mResourceData.length) { - return defValue; - } - - if (mResourceData[index] == null) { - return defValue; - } - - ColorStateList colorStateList = ResourceHelper.getColorStateList( - mResourceData[index], mContext); - if (colorStateList != null) { - return colorStateList.getDefaultColor(); - } - - return defValue; - } - - @Override - public ColorStateList getColorStateList(int index) { - if (!hasValue(index)) { - return null; - } - - return ResourceHelper.getColorStateList(mResourceData[index], mContext); - } - - @Override - public ComplexColor getComplexColor(int index) { - if (!hasValue(index)) { - return null; - } - - return ResourceHelper.getComplexColor(mResourceData[index], mContext); - } - - /** - * Retrieve the integer value for the attribute at <var>index</var>. - * - * @param index Index of attribute to retrieve. - * @param defValue Value to return if the attribute is not defined or - * not a resource. - * - * @return Attribute integer value, or defValue if not defined. - */ - @Override - public int getInteger(int index, int defValue) { - return getInt(index, defValue); - } - - /** - * Retrieve a dimensional unit attribute at <var>index</var>. Unit - * conversions are based on the current {@link DisplayMetrics} - * associated with the resources this {@link TypedArray} object - * came from. - * - * @param index Index of attribute to retrieve. - * @param defValue Value to return if the attribute is not defined or - * not a resource. - * - * @return Attribute dimension value multiplied by the appropriate - * metric, or defValue if not defined. - * - * @see #getDimensionPixelOffset - * @see #getDimensionPixelSize - */ - @Override - public float getDimension(int index, float defValue) { - String s = getString(index); - if (s == null) { - return defValue; - } - // Check if the value is a magic constant that doesn't require a unit. - try { - int i = Integer.parseInt(s); - if (i == LayoutParams.MATCH_PARENT || i == LayoutParams.WRAP_CONTENT) { - return i; - } - } catch (NumberFormatException ignored) { - // pass - } - - if (ResourceHelper.parseFloatAttribute(mNames[index], s, mValue, true)) { - return mValue.getDimension(mBridgeResources.getDisplayMetrics()); - } - - return defValue; - } - - /** - * Retrieve a dimensional unit attribute at <var>index</var> for use - * as an offset in raw pixels. This is the same as - * {@link #getDimension}, except the returned value is converted to - * integer pixels for you. An offset conversion involves simply - * truncating the base value to an integer. - * - * @param index Index of attribute to retrieve. - * @param defValue Value to return if the attribute is not defined or - * not a resource. - * - * @return Attribute dimension value multiplied by the appropriate - * metric and truncated to integer pixels, or defValue if not defined. - * - * @see #getDimension - * @see #getDimensionPixelSize - */ - @Override - public int getDimensionPixelOffset(int index, int defValue) { - return (int) getDimension(index, defValue); - } - - /** - * Retrieve a dimensional unit attribute at <var>index</var> for use - * as a size in raw pixels. This is the same as - * {@link #getDimension}, except the returned value is converted to - * integer pixels for use as a size. A size conversion involves - * rounding the base value, and ensuring that a non-zero base value - * is at least one pixel in size. - * - * @param index Index of attribute to retrieve. - * @param defValue Value to return if the attribute is not defined or - * not a resource. - * - * @return Attribute dimension value multiplied by the appropriate - * metric and truncated to integer pixels, or defValue if not defined. - * - * @see #getDimension - * @see #getDimensionPixelOffset - */ - @Override - public int getDimensionPixelSize(int index, int defValue) { - try { - return getDimension(index, null); - } catch (RuntimeException e) { - String s = getString(index); - - if (s != null) { - // looks like we were unable to resolve the dimension value - Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT, - String.format("\"%1$s\" in attribute \"%2$s\" is not a valid format.", - s, mNames[index]), null); - } - - return defValue; - } - } - - /** - * Special version of {@link #getDimensionPixelSize} for retrieving - * {@link android.view.ViewGroup}'s layout_width and layout_height - * attributes. This is only here for performance reasons; applications - * should use {@link #getDimensionPixelSize}. - * - * @param index Index of the attribute to retrieve. - * @param name Textual name of attribute for error reporting. - * - * @return Attribute dimension value multiplied by the appropriate - * metric and truncated to integer pixels. - */ - @Override - public int getLayoutDimension(int index, String name) { - try { - // this will throw an exception if not found. - return getDimension(index, name); - } catch (RuntimeException e) { - - if (LayoutInflater_Delegate.sIsInInclude) { - throw new RuntimeException("Layout Dimension '" + name + "' not found."); - } - - Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT, - "You must supply a " + name + " attribute.", null); - - return 0; - } - } - - @Override - public int getLayoutDimension(int index, int defValue) { - return getDimensionPixelSize(index, defValue); - } - - /** @param name attribute name, used for error reporting. */ - private int getDimension(int index, @Nullable String name) { - String s = getString(index); - if (s == null) { - if (name != null) { - throw new RuntimeException("Attribute '" + name + "' not found"); - } - throw new RuntimeException(); - } - // Check if the value is a magic constant that doesn't require a unit. - try { - int i = Integer.parseInt(s); - if (i == LayoutParams.MATCH_PARENT || i == LayoutParams.WRAP_CONTENT) { - return i; - } - } catch (NumberFormatException ignored) { - // pass - } - if (ResourceHelper.parseFloatAttribute(mNames[index], s, mValue, true)) { - float f = mValue.getDimension(mBridgeResources.getDisplayMetrics()); - - final int res = (int)(f+0.5f); - if (res != 0) return res; - if (f == 0) return 0; - if (f > 0) return 1; - } - - throw new RuntimeException(); - } - - /** - * Retrieve a fractional unit attribute at <var>index</var>. - * - * @param index Index of attribute to retrieve. - * @param base The base value of this fraction. In other words, a - * standard fraction is multiplied by this value. - * @param pbase The parent base value of this fraction. In other - * words, a parent fraction (nn%p) is multiplied by this - * value. - * @param defValue Value to return if the attribute is not defined or - * not a resource. - * - * @return Attribute fractional value multiplied by the appropriate - * base value, or defValue if not defined. - */ - @Override - public float getFraction(int index, int base, int pbase, float defValue) { - String value = getString(index); - if (value == null) { - return defValue; - } - - if (ResourceHelper.parseFloatAttribute(mNames[index], value, mValue, false)) { - return mValue.getFraction(base, pbase); - } - - // looks like we were unable to resolve the fraction value - Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT, - String.format( - "\"%1$s\" in attribute \"%2$s\" cannot be converted to a fraction.", - value, mNames[index]), null); - - return defValue; - } - - /** - * Retrieve the resource identifier for the attribute at - * <var>index</var>. Note that attribute resource as resolved when - * the overall {@link TypedArray} object is retrieved. As a - * result, this function will return the resource identifier of the - * final resource value that was found, <em>not</em> necessarily the - * original resource that was specified by the attribute. - * - * @param index Index of attribute to retrieve. - * @param defValue Value to return if the attribute is not defined or - * not a resource. - * - * @return Attribute resource identifier, or defValue if not defined. - */ - @Override - public int getResourceId(int index, int defValue) { - if (index < 0 || index >= mResourceData.length) { - return defValue; - } - - // get the Resource for this index - ResourceValue resValue = mResourceData[index]; - - // no data, return the default value. - if (resValue == null) { - return defValue; - } - - // check if this is a style resource - if (resValue instanceof StyleResourceValue) { - // get the id that will represent this style. - return mContext.getDynamicIdByStyle((StyleResourceValue)resValue); - } - - // if the attribute was a reference to a resource, and not a declaration of an id (@+id), - // then the xml attribute value was "resolved" which leads us to a ResourceValue with a - // valid getType() and getName() returning a resource name. - // (and getValue() returning null!). We need to handle this! - if (resValue.getResourceType() != null) { - // if this is a framework id - if (mPlatformFile || resValue.isFramework()) { - // look for idName in the android R classes - return mContext.getFrameworkResourceValue( - resValue.getResourceType(), resValue.getName(), defValue); - } - - // look for idName in the project R class. - return mContext.getProjectResourceValue( - resValue.getResourceType(), resValue.getName(), defValue); - } - - // else, try to get the value, and resolve it somehow. - String value = resValue.getValue(); - if (value == null) { - return defValue; - } - value = value.trim(); - - // if the value is just an integer, return it. - try { - int i = Integer.parseInt(value); - if (Integer.toString(i).equals(value)) { - return i; - } - } catch (NumberFormatException e) { - // pass - } - - if (value.startsWith("#")) { - // this looks like a color, do not try to parse it - return defValue; - } - - // Handle the @id/<name>, @+id/<name> and @android:id/<name> - // We need to return the exact value that was compiled (from the various R classes), - // as these values can be reused internally with calls to findViewById(). - // There's a trick with platform layouts that not use "android:" but their IDs are in - // fact in the android.R and com.android.internal.R classes. - // The field mPlatformFile will indicate that all IDs are to be looked up in the android R - // classes exclusively. - - // if this is a reference to an id, find it. - if (value.startsWith("@id/") || value.startsWith("@+") || - value.startsWith("@android:id/")) { - - int pos = value.indexOf('/'); - String idName = value.substring(pos + 1); - boolean create = value.startsWith("@+"); - boolean isFrameworkId = - mPlatformFile || value.startsWith("@android") || value.startsWith("@+android"); - - // Look for the idName in project or android R class depending on isPlatform. - if (create) { - Integer idValue; - if (isFrameworkId) { - idValue = Bridge.getResourceId(ResourceType.ID, idName); - } else { - idValue = mContext.getLayoutlibCallback().getResourceId(ResourceType.ID, idName); - } - return idValue == null ? defValue : idValue; - } - // This calls the same method as in if(create), but doesn't create a dynamic id, if - // one is not found. - if (isFrameworkId) { - return mContext.getFrameworkResourceValue(ResourceType.ID, idName, defValue); - } else { - return mContext.getProjectResourceValue(ResourceType.ID, idName, defValue); - } - } - else if (value.startsWith("@aapt:_aapt")) { - return mContext.getLayoutlibCallback().getResourceId(ResourceType.AAPT, value); - } - - // not a direct id valid reference. First check if it's an enum (this is a corner case - // for attributes that have a reference|enum type), then fallback to resolve - // as an ID without prefix. - Integer enumValue = resolveEnumAttribute(index); - if (enumValue != null) { - return enumValue; - } - - // Ok, not an enum, resolve as an ID - Integer idValue; - - if (resValue.isFramework()) { - idValue = Bridge.getResourceId(resValue.getResourceType(), - resValue.getName()); - } else { - idValue = mContext.getLayoutlibCallback().getResourceId( - resValue.getResourceType(), resValue.getName()); - } - - if (idValue != null) { - return idValue; - } - - Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE, - String.format( - "Unable to resolve id \"%1$s\" for attribute \"%2$s\"", value, mNames[index]), - resValue); - - return defValue; - } - - @Override - public int getThemeAttributeId(int index, int defValue) { - // TODO: Get the right Theme Attribute ID to enable caching of the drawables. - return defValue; - } - - /** - * Retrieve the Drawable for the attribute at <var>index</var>. This - * gets the resource ID of the selected attribute, and uses - * {@link Resources#getDrawable Resources.getDrawable} of the owning - * Resources object to retrieve its Drawable. - * - * @param index Index of attribute to retrieve. - * - * @return Drawable for the attribute, or null if not defined. - */ - @Override - public Drawable getDrawable(int index) { - if (!hasValue(index)) { - return null; - } - - ResourceValue value = mResourceData[index]; - return ResourceHelper.getDrawable(value, mContext, mTheme); - } - - /** - * Version of {@link #getDrawable(int)} that accepts an override density. - * @hide - */ - @Override - public Drawable getDrawableForDensity(int index, int density) { - return getDrawable(index); - } - - /** - * Retrieve the Typeface for the attribute at <var>index</var>. - * @param index Index of attribute to retrieve. - * - * @return Typeface for the attribute, or null if not defined. - */ - @Override - public Typeface getFont(int index) { - if (!hasValue(index)) { - return null; - } - - ResourceValue value = mResourceData[index]; - return ResourceHelper.getFont(value, mContext, mTheme); - } - - /** - * Retrieve the CharSequence[] for the attribute at <var>index</var>. - * This gets the resource ID of the selected attribute, and uses - * {@link Resources#getTextArray Resources.getTextArray} of the owning - * Resources object to retrieve its String[]. - * - * @param index Index of attribute to retrieve. - * - * @return CharSequence[] for the attribute, or null if not defined. - */ - @Override - public CharSequence[] getTextArray(int index) { - if (!hasValue(index)) { - return null; - } - ResourceValue resVal = mResourceData[index]; - if (resVal instanceof ArrayResourceValue) { - ArrayResourceValue array = (ArrayResourceValue) resVal; - int count = array.getElementCount(); - return count >= 0 ? Resources_Delegate.fillValues(mBridgeResources, array, new CharSequence[count]) : - null; - } - int id = getResourceId(index, 0); - String resIdMessage = id > 0 ? " (resource id 0x" + Integer.toHexString(id) + ')' : ""; - assert false : - String.format("%1$s in %2$s%3$s is not a valid array resource.", resVal.getValue(), - mNames[index], resIdMessage); - - return new CharSequence[0]; - } - - @Override - public int[] extractThemeAttrs() { - // The drawables are always inflated with a Theme and we don't care about caching. So, - // just return. - return null; - } - - @Override - public int getChangingConfigurations() { - // We don't care about caching. Any change in configuration is a fresh render. So, - // just return. - return 0; - } - - /** - * Retrieve the raw TypedValue for the attribute at <var>index</var>. - * - * @param index Index of attribute to retrieve. - * @param outValue TypedValue object in which to place the attribute's - * data. - * - * @return Returns true if the value was retrieved, else false. - */ - @Override - public boolean getValue(int index, TypedValue outValue) { - // TODO: more switch cases for other types. - outValue.type = getType(index); - switch (outValue.type) { - case TYPE_NULL: - return false; - case TYPE_STRING: - outValue.string = getString(index); - return true; - default: - // For back-compatibility, parse as float. - String s = getString(index); - return s != null && - ResourceHelper.parseFloatAttribute(mNames[index], s, outValue, false); - } - } - - @Override - @SuppressWarnings("ResultOfMethodCallIgnored") - public int getType(int index) { - String value = getString(index); - if (value == null) { - return TYPE_NULL; - } - if (value.startsWith(PREFIX_RESOURCE_REF)) { - return TYPE_REFERENCE; - } - if (value.startsWith(PREFIX_THEME_REF)) { - return TYPE_ATTRIBUTE; - } - try { - // Don't care about the value. Only called to check if an exception is thrown. - convertValueToInt(value, 0); - if (value.startsWith("0x") || value.startsWith("0X")) { - return TYPE_INT_HEX; - } - // is it a color? - if (value.startsWith("#")) { - int length = value.length() - 1; - if (length == 3) { // rgb - return TYPE_INT_COLOR_RGB4; - } - if (length == 4) { // argb - return TYPE_INT_COLOR_ARGB4; - } - if (length == 6) { // rrggbb - return TYPE_INT_COLOR_RGB8; - } - if (length == 8) { // aarrggbb - return TYPE_INT_COLOR_ARGB8; - } - } - if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false")) { - return TYPE_INT_BOOLEAN; - } - return TYPE_INT_DEC; - } catch (NumberFormatException ignored) { - try { - Float.parseFloat(value); - return TYPE_FLOAT; - } catch (NumberFormatException ignore) { - } - // Might be a dimension. - if (ResourceHelper.parseFloatAttribute(null, value, new TypedValue(), false)) { - return TYPE_DIMENSION; - } - } - // TODO: handle fractions. - return TYPE_STRING; - } - - /** - * Determines whether there is an attribute at <var>index</var>. - * - * @param index Index of attribute to retrieve. - * - * @return True if the attribute has a value, false otherwise. - */ - @Override - public boolean hasValue(int index) { - return index >= 0 && index < mResourceData.length && mResourceData[index] != null; - } - - @Override - public boolean hasValueOrEmpty(int index) { - return hasValue(index) || index >= 0 && index < mResourceData.length && - mEmptyIds != null && Arrays.binarySearch(mEmptyIds, index) >= 0; - } - - /** - * Retrieve the raw TypedValue for the attribute at <var>index</var> - * and return a temporary object holding its data. This object is only - * valid until the next call on to {@link TypedArray}. - * - * @param index Index of attribute to retrieve. - * - * @return Returns a TypedValue object if the attribute is defined, - * containing its data; otherwise returns null. (You will not - * receive a TypedValue whose type is TYPE_NULL.) - */ - @Override - public TypedValue peekValue(int index) { - if (index < 0 || index >= mResourceData.length) { - return null; - } - - if (getValue(index, mValue)) { - return mValue; - } - - return null; - } - - /** - * Returns a message about the parser state suitable for printing error messages. - */ - @Override - public String getPositionDescription() { - return "<internal -- stub if needed>"; - } - - /** - * Give back a previously retrieved TypedArray, for later re-use. - */ - @Override - public void recycle() { - // pass - } - - @Override - public String toString() { - return Arrays.toString(mResourceData); - } - - /** - * Searches for the string in the attributes (flag or enums) and returns the integer. - * If found, it will return an integer matching the value. - * - * @param index Index of attribute to retrieve. - * - * @return Attribute int value, or null if not defined. - */ - private Integer resolveEnumAttribute(int index) { - // Get the map of attribute-constant -> IntegerValue - Map<String, Integer> map = null; - if (mIsFramework[index]) { - map = Bridge.getEnumValues(mNames[index]); - } else { - // get the styleable matching the resolved name - RenderResources res = mContext.getRenderResources(); - ResourceValue attr = res.getProjectResource(ResourceType.ATTR, mNames[index]); - if (attr instanceof AttrResourceValue) { - map = ((AttrResourceValue) attr).getAttributeValues(); - } - } - - if (map != null) { - // accumulator to store the value of the 1+ constants. - int result = 0; - boolean found = false; - - // split the value in case this is a mix of several flags. - String[] keywords = mResourceData[index].getValue().split("\\|"); - for (String keyword : keywords) { - Integer i = map.get(keyword.trim()); - if (i != null) { - result |= i; - found = true; - } - // TODO: We should act smartly and log a warning for incorrect keywords. However, - // this method is currently called even if the resourceValue is not an enum. - } - if (found) { - return result; - } - } - - return null; - } - - /** - * Copied from {@link XmlUtils#convertValueToInt(CharSequence, int)}, but adapted to account - * for aapt, and the fact that host Java VM's Integer.parseInt("XXXXXXXX", 16) cannot handle - * "XXXXXXXX" > 80000000. - */ - private static int convertValueToInt(@Nullable String charSeq, int defValue) { - if (null == charSeq || charSeq.isEmpty()) - return defValue; - - int sign = 1; - int index = 0; - int len = charSeq.length(); - int base = 10; - - if ('-' == charSeq.charAt(0)) { - sign = -1; - index++; - } - - if ('0' == charSeq.charAt(index)) { - // Quick check for a zero by itself - if (index == (len - 1)) - return 0; - - char c = charSeq.charAt(index + 1); - - if ('x' == c || 'X' == c) { - index += 2; - base = 16; - } else { - index++; - // Leave the base as 10. aapt removes the preceding zero, and thus when framework - // sees the value, it only gets the decimal value. - } - } else if ('#' == charSeq.charAt(index)) { - return ResourceHelper.getColor(charSeq) * sign; - } else if ("true".equals(charSeq) || "TRUE".equals(charSeq)) { - return -1; - } else if ("false".equals(charSeq) || "FALSE".equals(charSeq)) { - return 0; - } - - // Use Long, since we want to handle hex ints > 80000000. - return ((int)Long.parseLong(charSeq.substring(index), base)) * sign; - } - - static TypedArray obtain(Resources res, int len) { - return new BridgeTypedArray(res, null, len, true); - } -} diff --git a/tools/layoutlib/bridge/src/android/content/res/ComplexColor_Accessor.java b/tools/layoutlib/bridge/src/android/content/res/ComplexColor_Accessor.java deleted file mode 100644 index 09c0260196cf..000000000000 --- a/tools/layoutlib/bridge/src/android/content/res/ComplexColor_Accessor.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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 android.content.res; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.res.Resources.Theme; -import android.util.AttributeSet; - -import java.io.IOException; - -/** - * Class that provides access to the {@link GradientColor#createFromXmlInner(Resources, - * XmlPullParser, AttributeSet, Theme)} and {@link ColorStateList#createFromXmlInner(Resources, - * XmlPullParser, AttributeSet, Theme)} methods - */ -public class ComplexColor_Accessor { - public static GradientColor createGradientColorFromXmlInner(@NonNull Resources r, - @NonNull XmlPullParser parser, @NonNull AttributeSet attrs, @Nullable Theme theme) - throws IOException, XmlPullParserException { - return GradientColor.createFromXmlInner(r, parser, attrs, theme); - } - - public static ColorStateList createColorStateListFromXmlInner(@NonNull Resources r, - @NonNull XmlPullParser parser, @NonNull AttributeSet attrs, @Nullable Theme theme) - throws IOException, XmlPullParserException { - return ColorStateList.createFromXmlInner(r, parser, attrs, theme); - } -} diff --git a/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java deleted file mode 100644 index c20ee12ee30c..000000000000 --- a/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java +++ /dev/null @@ -1,1025 +0,0 @@ -/* - * 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 android.content.res; - -import com.android.SdkConstants; -import com.android.ide.common.rendering.api.ArrayResourceValue; -import com.android.ide.common.rendering.api.DensityBasedResourceValue; -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.ide.common.rendering.api.LayoutlibCallback; -import com.android.ide.common.rendering.api.PluralsResourceValue; -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.BridgeConstants; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; -import com.android.layoutlib.bridge.impl.ParserFactory; -import com.android.layoutlib.bridge.impl.ResourceHelper; -import com.android.layoutlib.bridge.util.NinePatchInputStream; -import com.android.ninepatch.NinePatch; -import com.android.resources.ResourceType; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; -import com.android.util.Pair; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.res.Resources.NotFoundException; -import android.content.res.Resources.Theme; -import android.graphics.Typeface; -import android.graphics.drawable.Drawable; -import android.icu.text.PluralRules; -import android.util.AttributeSet; -import android.util.DisplayMetrics; -import android.util.LruCache; -import android.util.TypedValue; -import android.view.DisplayAdjustments; -import android.view.ViewGroup.LayoutParams; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.util.Iterator; - -@SuppressWarnings("deprecation") -public class Resources_Delegate { - - private static boolean[] mPlatformResourceFlag = new boolean[1]; - // TODO: This cache is cleared every time a render session is disposed. Look into making this - // more long lived. - private static LruCache<String, Drawable.ConstantState> sDrawableCache = new LruCache<>(50); - - public static Resources initSystem(BridgeContext context, - AssetManager assets, - DisplayMetrics metrics, - Configuration config, - LayoutlibCallback layoutlibCallback) { - Resources resources = new Resources(Resources_Delegate.class.getClassLoader()); - resources.setImpl(new ResourcesImpl(assets, metrics, config, new DisplayAdjustments())); - resources.mContext = context; - resources.mLayoutlibCallback = layoutlibCallback; - return Resources.mSystem = resources; - } - - /** - * Disposes the static {@link Resources#mSystem} to make sure we don't leave objects around that - * would prevent us from unloading the library. - */ - public static void disposeSystem() { - sDrawableCache.evictAll(); - Resources.mSystem.mContext = null; - Resources.mSystem.mLayoutlibCallback = null; - Resources.mSystem = null; - } - - public static BridgeTypedArray newTypeArray(Resources resources, int numEntries, - boolean platformFile) { - return new BridgeTypedArray(resources, resources.mContext, numEntries, platformFile); - } - - private static Pair<ResourceType, String> getResourceInfo(Resources resources, int id, - boolean[] platformResFlag_out) { - // first get the String related to this id in the framework - Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(id); - - // Set the layoutlib callback and context for resources - if (resources != Resources.mSystem && resources.mLayoutlibCallback == null) { - resources.mLayoutlibCallback = Resources.mSystem.mLayoutlibCallback; - resources.mContext = Resources.mSystem.mContext; - } - - if (resourceInfo != null) { - platformResFlag_out[0] = true; - return resourceInfo; - } - - // didn't find a match in the framework? look in the project. - if (resources.mLayoutlibCallback != null) { - resourceInfo = resources.mLayoutlibCallback.resolveResourceId(id); - - if (resourceInfo != null) { - platformResFlag_out[0] = false; - return resourceInfo; - } - } - return null; - } - - private static Pair<String, ResourceValue> getResourceValue(Resources resources, int id, - boolean[] platformResFlag_out) { - Pair<ResourceType, String> resourceInfo = - getResourceInfo(resources, id, platformResFlag_out); - - if (resourceInfo != null) { - String attributeName = resourceInfo.getSecond(); - RenderResources renderResources = resources.mContext.getRenderResources(); - ResourceValue value = platformResFlag_out[0] ? - renderResources.getFrameworkResource(resourceInfo.getFirst(), attributeName) : - renderResources.getProjectResource(resourceInfo.getFirst(), attributeName); - - if (value == null) { - // Unable to resolve the attribute, just leave the unresolved value - value = new ResourceValue(resourceInfo.getFirst(), attributeName, attributeName, - platformResFlag_out[0]); - } - return Pair.of(attributeName, value); - } - - return null; - } - - @LayoutlibDelegate - static Drawable getDrawable(Resources resources, int id) { - return getDrawable(resources, id, null); - } - - @LayoutlibDelegate - static Drawable getDrawable(Resources resources, int id, Theme theme) { - Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag); - if (value != null) { - String key = value.getSecond().getValue(); - - Drawable.ConstantState constantState = key != null ? sDrawableCache.get(key) : null; - Drawable drawable; - if (constantState != null) { - drawable = constantState.newDrawable(resources, theme); - } else { - drawable = - ResourceHelper.getDrawable(value.getSecond(), resources.mContext, theme); - - if (key != null) { - sDrawableCache.put(key, drawable.getConstantState()); - } - } - - return drawable; - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(resources, id); - - // this is not used since the method above always throws - return null; - } - - @LayoutlibDelegate - static int getColor(Resources resources, int id) { - return getColor(resources, id, null); - } - - @LayoutlibDelegate - static int getColor(Resources resources, int id, Theme theme) throws NotFoundException { - Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag); - - if (value != null) { - ResourceValue resourceValue = value.getSecond(); - try { - return ResourceHelper.getColor(resourceValue.getValue()); - } catch (NumberFormatException e) { - // Check if the value passed is a file. If it is, mostly likely, user is referencing - // a color state list from a place where they should reference only a pure color. - String message; - if (new File(resourceValue.getValue()).isFile()) { - String resource = (resourceValue.isFramework() ? "@android:" : "@") + "color/" - + resourceValue.getName(); - message = "Hexadecimal color expected, found Color State List for " + resource; - } else { - message = e.getMessage(); - } - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, message, e, null); - return 0; - } - } - - // Suppress possible NPE. getColorStateList will never return null, it will instead - // throw an exception, but intelliJ can't figure that out - //noinspection ConstantConditions - return getColorStateList(resources, id, theme).getDefaultColor(); - } - - @LayoutlibDelegate - static ColorStateList getColorStateList(Resources resources, int id) throws NotFoundException { - return getColorStateList(resources, id, null); - } - - @LayoutlibDelegate - static ColorStateList getColorStateList(Resources resources, int id, Theme theme) - throws NotFoundException { - Pair<String, ResourceValue> resValue = - getResourceValue(resources, id, mPlatformResourceFlag); - - if (resValue != null) { - ColorStateList stateList = ResourceHelper.getColorStateList(resValue.getSecond(), - resources.mContext); - if (stateList != null) { - return stateList.obtainForTheme(theme); - } - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(resources, id); - - // this is not used since the method above always throws - return null; - } - - @LayoutlibDelegate - static CharSequence getText(Resources resources, int id, CharSequence def) { - Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag); - - if (value != null) { - ResourceValue resValue = value.getSecond(); - - assert resValue != null; - if (resValue != null) { - String v = resValue.getValue(); - if (v != null) { - return v; - } - } - } - - return def; - } - - @LayoutlibDelegate - static CharSequence getText(Resources resources, int id) throws NotFoundException { - Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag); - - if (value != null) { - ResourceValue resValue = value.getSecond(); - - assert resValue != null; - if (resValue != null) { - String v = resValue.getValue(); - if (v != null) { - return v; - } - } - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(resources, id); - - // this is not used since the method above always throws - return null; - } - - @LayoutlibDelegate - static CharSequence[] getTextArray(Resources resources, int id) throws NotFoundException { - ResourceValue resValue = getArrayResourceValue(resources, id); - if (resValue == null) { - // Error already logged by getArrayResourceValue. - return new CharSequence[0]; - } else if (!(resValue instanceof ArrayResourceValue)) { - return new CharSequence[]{ - resolveReference(resources, resValue.getValue(), resValue.isFramework())}; - } - ArrayResourceValue arv = ((ArrayResourceValue) resValue); - return fillValues(resources, arv, new CharSequence[arv.getElementCount()]); - } - - @LayoutlibDelegate - static String[] getStringArray(Resources resources, int id) throws NotFoundException { - ResourceValue resValue = getArrayResourceValue(resources, id); - if (resValue == null) { - // Error already logged by getArrayResourceValue. - return new String[0]; - } else if (!(resValue instanceof ArrayResourceValue)) { - return new String[]{ - resolveReference(resources, resValue.getValue(), resValue.isFramework())}; - } - ArrayResourceValue arv = ((ArrayResourceValue) resValue); - return fillValues(resources, arv, new String[arv.getElementCount()]); - } - - /** - * Resolve each element in resValue and copy them to {@code values}. The values copied are - * always Strings. The ideal signature for the method should be <T super String>, but java - * generics don't support it. - */ - static <T extends CharSequence> T[] fillValues(Resources resources, ArrayResourceValue resValue, - T[] values) { - int i = 0; - for (Iterator<String> iterator = resValue.iterator(); iterator.hasNext(); i++) { - @SuppressWarnings("unchecked") - T s = (T) resolveReference(resources, iterator.next(), resValue.isFramework()); - values[i] = s; - } - return values; - } - - @LayoutlibDelegate - static int[] getIntArray(Resources resources, int id) throws NotFoundException { - ResourceValue rv = getArrayResourceValue(resources, id); - if (rv == null) { - // Error already logged by getArrayResourceValue. - return new int[0]; - } else if (!(rv instanceof ArrayResourceValue)) { - // This is an older IDE that can only give us the first element of the array. - String firstValue = resolveReference(resources, rv.getValue(), rv.isFramework()); - try { - return new int[]{getInt(firstValue)}; - } catch (NumberFormatException e) { - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, - "Integer resource array contains non-integer value: " + - firstValue, null); - return new int[1]; - } - } - ArrayResourceValue resValue = ((ArrayResourceValue) rv); - int[] values = new int[resValue.getElementCount()]; - int i = 0; - for (Iterator<String> iterator = resValue.iterator(); iterator.hasNext(); i++) { - String element = resolveReference(resources, iterator.next(), resValue.isFramework()); - try { - values[i] = getInt(element); - } catch (NumberFormatException e) { - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, - "Integer resource array contains non-integer value: " + element, null); - } - } - return values; - } - - /** - * Try to find the ArrayResourceValue for the given id. - * <p/> - * If the ResourceValue found is not of type {@link ResourceType#ARRAY}, the method logs an - * error and return null. However, if the ResourceValue found has type {@code - * ResourceType.ARRAY}, but the value is not an instance of {@link ArrayResourceValue}, the - * method returns the ResourceValue. This happens on older versions of the IDE, which did not - * parse the array resources properly. - * <p/> - * - * @throws NotFoundException if no resource if found - */ - @Nullable - private static ResourceValue getArrayResourceValue(Resources resources, int id) - throws NotFoundException { - Pair<String, ResourceValue> v = getResourceValue(resources, id, mPlatformResourceFlag); - - if (v != null) { - ResourceValue resValue = v.getSecond(); - - assert resValue != null; - if (resValue != null) { - final ResourceType type = resValue.getResourceType(); - if (type != ResourceType.ARRAY) { - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE, - String.format( - "Resource with id 0x%1$X is not an array resource, but %2$s", - id, type == null ? "null" : type.getDisplayName()), - null); - return null; - } - if (!(resValue instanceof ArrayResourceValue)) { - Bridge.getLog().warning(LayoutLog.TAG_UNSUPPORTED, - "Obtaining resource arrays via getTextArray, getStringArray or getIntArray is not fully supported in this version of the IDE.", - null); - } - return resValue; - } - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(resources, id); - - // this is not used since the method above always throws - return null; - } - - @NonNull - private static String resolveReference(Resources resources, @NonNull String ref, - boolean forceFrameworkOnly) { - if (ref.startsWith(SdkConstants.PREFIX_RESOURCE_REF) || ref.startsWith - (SdkConstants.PREFIX_THEME_REF)) { - ResourceValue rv = - resources.mContext.getRenderResources().findResValue(ref, forceFrameworkOnly); - rv = resources.mContext.getRenderResources().resolveResValue(rv); - if (rv != null) { - return rv.getValue(); - } - } - // Not a reference. - return ref; - } - - @LayoutlibDelegate - static XmlResourceParser getLayout(Resources resources, int id) throws NotFoundException { - Pair<String, ResourceValue> v = getResourceValue(resources, id, mPlatformResourceFlag); - - if (v != null) { - ResourceValue value = v.getSecond(); - XmlPullParser parser = null; - - try { - // check if the current parser can provide us with a custom parser. - if (!mPlatformResourceFlag[0]) { - parser = resources.mLayoutlibCallback.getParser(value); - } - - // create a new one manually if needed. - if (parser == null) { - File xml = new File(value.getValue()); - if (xml.isFile()) { - // we need to create a pull parser around the layout XML file, and then - // give that to our XmlBlockParser - parser = ParserFactory.create(xml, true); - } - } - - if (parser != null) { - return new BridgeXmlBlockParser(parser, resources.mContext, - mPlatformResourceFlag[0]); - } - } catch (XmlPullParserException e) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "Failed to configure parser for " + value.getValue(), e, null /*data*/); - // we'll return null below. - } catch (FileNotFoundException e) { - // this shouldn't happen since we check above. - } - - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(resources, id); - - // this is not used since the method above always throws - return null; - } - - @LayoutlibDelegate - static XmlResourceParser getAnimation(Resources resources, int id) throws NotFoundException { - Pair<String, ResourceValue> v = getResourceValue(resources, id, mPlatformResourceFlag); - - if (v != null) { - ResourceValue value = v.getSecond(); - XmlPullParser parser; - - try { - File xml = new File(value.getValue()); - if (xml.isFile()) { - // we need to create a pull parser around the layout XML file, and then - // give that to our XmlBlockParser - parser = ParserFactory.create(xml); - - return new BridgeXmlBlockParser(parser, resources.mContext, - mPlatformResourceFlag[0]); - } - } catch (XmlPullParserException e) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "Failed to configure parser for " + value.getValue(), e, null /*data*/); - // we'll return null below. - } catch (FileNotFoundException e) { - // this shouldn't happen since we check above. - } - - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(resources, id); - - // this is not used since the method above always throws - return null; - } - - @LayoutlibDelegate - static TypedArray obtainAttributes(Resources resources, AttributeSet set, int[] attrs) { - return resources.mContext.obtainStyledAttributes(set, attrs); - } - - @LayoutlibDelegate - static TypedArray obtainAttributes(Resources resources, Resources.Theme theme, AttributeSet - set, int[] attrs) { - return Resources.obtainAttributes_Original(resources, theme, set, attrs); - } - - @LayoutlibDelegate - static TypedArray obtainTypedArray(Resources resources, int id) throws NotFoundException { - throw new UnsupportedOperationException(); - } - - @LayoutlibDelegate - static float getDimension(Resources resources, int id) throws NotFoundException { - Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag); - - if (value != null) { - ResourceValue resValue = value.getSecond(); - - assert resValue != null; - if (resValue != null) { - String v = resValue.getValue(); - if (v != null) { - if (v.equals(BridgeConstants.MATCH_PARENT) || - v.equals(BridgeConstants.FILL_PARENT)) { - return LayoutParams.MATCH_PARENT; - } else if (v.equals(BridgeConstants.WRAP_CONTENT)) { - return LayoutParams.WRAP_CONTENT; - } - TypedValue tmpValue = new TypedValue(); - if (ResourceHelper.parseFloatAttribute( - value.getFirst(), v, tmpValue, true /*requireUnit*/) && - tmpValue.type == TypedValue.TYPE_DIMENSION) { - return tmpValue.getDimension(resources.getDisplayMetrics()); - } - } - } - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(resources, id); - - // this is not used since the method above always throws - return 0; - } - - @LayoutlibDelegate - static int getDimensionPixelOffset(Resources resources, int id) throws NotFoundException { - Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag); - - if (value != null) { - ResourceValue resValue = value.getSecond(); - - assert resValue != null; - if (resValue != null) { - String v = resValue.getValue(); - if (v != null) { - TypedValue tmpValue = new TypedValue(); - if (ResourceHelper.parseFloatAttribute( - value.getFirst(), v, tmpValue, true /*requireUnit*/) && - tmpValue.type == TypedValue.TYPE_DIMENSION) { - return TypedValue.complexToDimensionPixelOffset(tmpValue.data, - resources.getDisplayMetrics()); - } - } - } - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(resources, id); - - // this is not used since the method above always throws - return 0; - } - - @LayoutlibDelegate - static int getDimensionPixelSize(Resources resources, int id) throws NotFoundException { - Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag); - - if (value != null) { - ResourceValue resValue = value.getSecond(); - - assert resValue != null; - if (resValue != null) { - String v = resValue.getValue(); - if (v != null) { - TypedValue tmpValue = new TypedValue(); - if (ResourceHelper.parseFloatAttribute( - value.getFirst(), v, tmpValue, true /*requireUnit*/) && - tmpValue.type == TypedValue.TYPE_DIMENSION) { - return TypedValue.complexToDimensionPixelSize(tmpValue.data, - resources.getDisplayMetrics()); - } - } - } - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(resources, id); - - // this is not used since the method above always throws - return 0; - } - - @LayoutlibDelegate - static int getInteger(Resources resources, int id) throws NotFoundException { - Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag); - - if (value != null) { - ResourceValue resValue = value.getSecond(); - - assert resValue != null; - if (resValue != null) { - String v = resValue.getValue(); - if (v != null) { - try { - return getInt(v); - } catch (NumberFormatException e) { - // return exception below - } - } - } - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(resources, id); - - // this is not used since the method above always throws - return 0; - } - - @LayoutlibDelegate - static boolean getBoolean(Resources resources, int id) throws NotFoundException { - Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag); - - if (value != null) { - ResourceValue resValue = value.getSecond(); - - if (resValue != null) { - String v = resValue.getValue(); - if (v != null) { - return Boolean.parseBoolean(v); - } - } - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(resources, id); - - // this is not used since the method above always throws - return false; - } - - @LayoutlibDelegate - static String getResourceEntryName(Resources resources, int resid) throws NotFoundException { - Pair<ResourceType, String> resourceInfo = getResourceInfo(resources, resid, new boolean[1]); - if (resourceInfo != null) { - return resourceInfo.getSecond(); - } - throwException(resid, null); - return null; - - } - - @LayoutlibDelegate - static String getResourceName(Resources resources, int resid) throws NotFoundException { - boolean[] platformOut = new boolean[1]; - Pair<ResourceType, String> resourceInfo = getResourceInfo(resources, resid, platformOut); - String packageName; - if (resourceInfo != null) { - if (platformOut[0]) { - packageName = SdkConstants.ANDROID_NS_NAME; - } else { - packageName = resources.mContext.getPackageName(); - packageName = packageName == null ? SdkConstants.APP_PREFIX : packageName; - } - return packageName + ':' + resourceInfo.getFirst().getName() + '/' + - resourceInfo.getSecond(); - } - throwException(resid, null); - return null; - } - - @LayoutlibDelegate - static String getResourcePackageName(Resources resources, int resid) throws NotFoundException { - boolean[] platformOut = new boolean[1]; - Pair<ResourceType, String> resourceInfo = getResourceInfo(resources, resid, platformOut); - if (resourceInfo != null) { - if (platformOut[0]) { - return SdkConstants.ANDROID_NS_NAME; - } - String packageName = resources.mContext.getPackageName(); - return packageName == null ? SdkConstants.APP_PREFIX : packageName; - } - throwException(resid, null); - return null; - } - - @LayoutlibDelegate - static String getResourceTypeName(Resources resources, int resid) throws NotFoundException { - Pair<ResourceType, String> resourceInfo = getResourceInfo(resources, resid, new boolean[1]); - if (resourceInfo != null) { - return resourceInfo.getFirst().getName(); - } - throwException(resid, null); - return null; - } - - @LayoutlibDelegate - static String getString(Resources resources, int id, Object... formatArgs) - throws NotFoundException { - String s = getString(resources, id); - if (s != null) { - return String.format(s, formatArgs); - - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(resources, id); - - // this is not used since the method above always throws - return null; - } - - @LayoutlibDelegate - static String getString(Resources resources, int id) throws NotFoundException { - Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag); - - if (value != null && value.getSecond().getValue() != null) { - return value.getSecond().getValue(); - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(resources, id); - - // this is not used since the method above always throws - return null; - } - - @LayoutlibDelegate - static String getQuantityString(Resources resources, int id, int quantity) throws - NotFoundException { - Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag); - - if (value != null) { - if (value.getSecond() instanceof PluralsResourceValue) { - PluralsResourceValue pluralsResourceValue = (PluralsResourceValue) value.getSecond(); - PluralRules pluralRules = PluralRules.forLocale(resources.getConfiguration().getLocales() - .get(0)); - String strValue = pluralsResourceValue.getValue(pluralRules.select(quantity)); - if (strValue == null) { - strValue = pluralsResourceValue.getValue(PluralRules.KEYWORD_OTHER); - } - - return strValue; - } - else { - return value.getSecond().getValue(); - } - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(resources, id); - - // this is not used since the method above always throws - return null; - } - - @LayoutlibDelegate - static String getQuantityString(Resources resources, int id, int quantity, Object... formatArgs) - throws NotFoundException { - String raw = getQuantityString(resources, id, quantity); - return String.format(resources.getConfiguration().getLocales().get(0), raw, formatArgs); - } - - @LayoutlibDelegate - static CharSequence getQuantityText(Resources resources, int id, int quantity) throws - NotFoundException { - return getQuantityString(resources, id, quantity); - } - - @LayoutlibDelegate - static Typeface getFont(Resources resources, int id) throws - NotFoundException { - Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag); - if (value != null) { - return ResourceHelper.getFont(value.getSecond(), resources.mContext, null); - } - - throwException(resources, id); - - // this is not used since the method above always throws - return null; - } - - @LayoutlibDelegate - static Typeface getFont(Resources resources, TypedValue outValue, int id) throws - NotFoundException { - Resources_Delegate.getValue(resources, id, outValue, true); - if (outValue.string != null) { - return ResourceHelper.getFont(outValue.string.toString(), resources.mContext, null, - mPlatformResourceFlag[0]); - } - - throwException(resources, id); - - // this is not used since the method above always throws - return null; - } - - @LayoutlibDelegate - static void getValue(Resources resources, int id, TypedValue outValue, boolean resolveRefs) - throws NotFoundException { - Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag); - - if (value != null) { - ResourceValue resVal = value.getSecond(); - String v = resVal.getValue(); - - if (v != null) { - if (ResourceHelper.parseFloatAttribute(value.getFirst(), v, outValue, - false /*requireUnit*/)) { - return; - } - if (resVal instanceof DensityBasedResourceValue) { - outValue.density = - ((DensityBasedResourceValue) resVal).getResourceDensity().getDpiValue(); - } - - // else it's a string - outValue.type = TypedValue.TYPE_STRING; - outValue.string = v; - return; - } - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(resources, id); - } - - @LayoutlibDelegate - static void getValue(Resources resources, String name, TypedValue outValue, boolean resolveRefs) - throws NotFoundException { - throw new UnsupportedOperationException(); - } - - @LayoutlibDelegate - static XmlResourceParser getXml(Resources resources, int id) throws NotFoundException { - Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag); - - if (value != null) { - String v = value.getSecond().getValue(); - - if (v != null) { - // check this is a file - File f = new File(v); - if (f.isFile()) { - try { - XmlPullParser parser = ParserFactory.create(f); - - return new BridgeXmlBlockParser(parser, resources.mContext, - mPlatformResourceFlag[0]); - } catch (XmlPullParserException e) { - NotFoundException newE = new NotFoundException(); - newE.initCause(e); - throw newE; - } catch (FileNotFoundException e) { - NotFoundException newE = new NotFoundException(); - newE.initCause(e); - throw newE; - } - } - } - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(resources, id); - - // this is not used since the method above always throws - return null; - } - - @LayoutlibDelegate - static XmlResourceParser loadXmlResourceParser(Resources resources, int id, - String type) throws NotFoundException { - return resources.loadXmlResourceParser_Original(id, type); - } - - @LayoutlibDelegate - static XmlResourceParser loadXmlResourceParser(Resources resources, String file, int id, - int assetCookie, String type) throws NotFoundException { - // even though we know the XML file to load directly, we still need to resolve the - // id so that we can know if it's a platform or project resource. - // (mPlatformResouceFlag will get the result and will be used later). - getResourceValue(resources, id, mPlatformResourceFlag); - - File f = new File(file); - try { - XmlPullParser parser = ParserFactory.create(f); - - return new BridgeXmlBlockParser(parser, resources.mContext, mPlatformResourceFlag[0]); - } catch (XmlPullParserException e) { - NotFoundException newE = new NotFoundException(); - newE.initCause(e); - throw newE; - } catch (FileNotFoundException e) { - NotFoundException newE = new NotFoundException(); - newE.initCause(e); - throw newE; - } - } - - @LayoutlibDelegate - static InputStream openRawResource(Resources resources, int id) throws NotFoundException { - Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag); - - if (value != null) { - String path = value.getSecond().getValue(); - - if (path != null) { - // check this is a file - File f = new File(path); - if (f.isFile()) { - try { - // if it's a nine-patch return a custom input stream so that - // other methods (mainly bitmap factory) can detect it's a 9-patch - // and actually load it as a 9-patch instead of a normal bitmap - if (path.toLowerCase().endsWith(NinePatch.EXTENSION_9PATCH)) { - return new NinePatchInputStream(f); - } - return new FileInputStream(f); - } catch (FileNotFoundException e) { - NotFoundException newE = new NotFoundException(); - newE.initCause(e); - throw newE; - } - } - } - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(resources, id); - - // this is not used since the method above always throws - return null; - } - - @LayoutlibDelegate - static InputStream openRawResource(Resources resources, int id, TypedValue value) throws - NotFoundException { - getValue(resources, id, value, true); - - String path = value.string.toString(); - - File f = new File(path); - if (f.isFile()) { - try { - // if it's a nine-patch return a custom input stream so that - // other methods (mainly bitmap factory) can detect it's a 9-patch - // and actually load it as a 9-patch instead of a normal bitmap - if (path.toLowerCase().endsWith(NinePatch.EXTENSION_9PATCH)) { - return new NinePatchInputStream(f); - } - return new FileInputStream(f); - } catch (FileNotFoundException e) { - NotFoundException exception = new NotFoundException(); - exception.initCause(e); - throw exception; - } - } - - throw new NotFoundException(); - } - - @LayoutlibDelegate - static AssetFileDescriptor openRawResourceFd(Resources resources, int id) throws - NotFoundException { - throw new UnsupportedOperationException(); - } - - /** - * Builds and throws a {@link Resources.NotFoundException} based on a resource id and a resource - * type. - * - * @param id the id of the resource - * - * @throws NotFoundException - */ - private static void throwException(Resources resources, int id) throws NotFoundException { - throwException(id, getResourceInfo(resources, id, new boolean[1])); - } - - private static void throwException(int id, @Nullable Pair<ResourceType, String> resourceInfo) { - String message; - if (resourceInfo != null) { - message = String.format( - "Could not find %1$s resource matching value 0x%2$X (resolved name: %3$s) in current configuration.", - resourceInfo.getFirst(), id, resourceInfo.getSecond()); - } else { - message = String.format("Could not resolve resource value: 0x%1$X.", id); - } - - throw new NotFoundException(message); - } - - private static int getInt(String v) throws NumberFormatException { - int radix = 10; - if (v.startsWith("0x")) { - v = v.substring(2); - radix = 16; - } else if (v.startsWith("0")) { - radix = 8; - } - return Integer.parseInt(v, radix); - } -} diff --git a/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java deleted file mode 100644 index f1e8fc21ce0e..000000000000 --- a/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2011 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.content.res; - -import com.android.ide.common.rendering.api.ResourceReference; -import com.android.ide.common.rendering.api.StyleResourceValue; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.layoutlib.bridge.impl.RenderSessionImpl; -import com.android.resources.ResourceType; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.annotation.Nullable; -import android.content.res.Resources.NotFoundException; -import android.content.res.Resources.Theme; -import android.content.res.Resources.ThemeKey; -import android.util.AttributeSet; -import android.util.TypedValue; - -/** - * Delegate used to provide new implementation of a select few methods of {@link Resources.Theme} - * - * Through the layoutlib_create tool, the original methods of Theme have been replaced - * by calls to methods of the same name in this delegate class. - * - */ -public class Resources_Theme_Delegate { - - // ---- delegate manager ---- - - private static final DelegateManager<Resources_Theme_Delegate> sManager = - new DelegateManager<Resources_Theme_Delegate>(Resources_Theme_Delegate.class); - - public static DelegateManager<Resources_Theme_Delegate> getDelegateManager() { - return sManager; - } - - // ---- delegate methods. ---- - - @LayoutlibDelegate - /*package*/ static TypedArray obtainStyledAttributes( - Resources thisResources, Theme thisTheme, - int[] attrs) { - boolean changed = setupResources(thisTheme); - BridgeTypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(attrs); - ta.setTheme(thisTheme); - restoreResources(changed); - return ta; - } - - @LayoutlibDelegate - /*package*/ static TypedArray obtainStyledAttributes( - Resources thisResources, Theme thisTheme, - int resid, int[] attrs) - throws NotFoundException { - boolean changed = setupResources(thisTheme); - BridgeTypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(resid, - attrs); - ta.setTheme(thisTheme); - restoreResources(changed); - return ta; - } - - @LayoutlibDelegate - /*package*/ static TypedArray obtainStyledAttributes( - Resources thisResources, Theme thisTheme, - AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) { - boolean changed = setupResources(thisTheme); - BridgeTypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(set, - attrs, defStyleAttr, defStyleRes); - ta.setTheme(thisTheme); - restoreResources(changed); - return ta; - } - - @LayoutlibDelegate - /*package*/ static boolean resolveAttribute( - Resources thisResources, Theme thisTheme, - int resid, TypedValue outValue, - boolean resolveRefs) { - boolean changed = setupResources(thisTheme); - boolean found = RenderSessionImpl.getCurrentContext().resolveThemeAttribute(resid, - outValue, resolveRefs); - restoreResources(changed); - return found; - } - - @LayoutlibDelegate - /*package*/ static TypedArray resolveAttributes(Resources thisResources, Theme thisTheme, - int[] values, int[] attrs) { - // FIXME - return null; - } - - // ---- private helper methods ---- - - private static boolean setupResources(Theme thisTheme) { - // Key is a space-separated list of theme ids applied that have been merged into the - // BridgeContext's theme to make thisTheme. - final ThemeKey key = thisTheme.getKey(); - final int[] resId = key.mResId; - final boolean[] force = key.mForce; - - boolean changed = false; - for (int i = 0, N = key.mCount; i < N; i++) { - StyleResourceValue style = resolveStyle(resId[i]); - if (style != null) { - RenderSessionImpl.getCurrentContext().getRenderResources().applyStyle( - style, force[i]); - changed = true; - } - - } - return changed; - } - - private static void restoreResources(boolean changed) { - if (changed) { - RenderSessionImpl.getCurrentContext().getRenderResources().clearStyles(); - } - } - - @Nullable - private static StyleResourceValue resolveStyle(int nativeResid) { - if (nativeResid == 0) { - return null; - } - BridgeContext context = RenderSessionImpl.getCurrentContext(); - ResourceReference theme = context.resolveId(nativeResid); - if (theme.isFramework()) { - return (StyleResourceValue) context.getRenderResources() - .getFrameworkResource(ResourceType.STYLE, theme.getName()); - } else { - return (StyleResourceValue) context.getRenderResources() - .getProjectResource(ResourceType.STYLE, theme.getName()); - } - } -} diff --git a/tools/layoutlib/bridge/src/android/content/res/TypedArray_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/TypedArray_Delegate.java deleted file mode 100644 index faa8852b494e..000000000000 --- a/tools/layoutlib/bridge/src/android/content/res/TypedArray_Delegate.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2011 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.content.res; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.util.TypedValue; - -public class TypedArray_Delegate { - - @LayoutlibDelegate - public static boolean getValueAt(TypedArray theTypedArray, int index, TypedValue outValue) { - // pass - return false; - } - - @LayoutlibDelegate - /*package*/ static TypedArray obtain(Resources res, int len) { - return BridgeTypedArray.obtain(res, len); - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/BaseCanvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BaseCanvas_Delegate.java deleted file mode 100644 index cc71053fced6..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/BaseCanvas_Delegate.java +++ /dev/null @@ -1,762 +0,0 @@ -/* - * 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 android.graphics; - -import com.android.ide.common.rendering.api.LayoutLog; -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; -import android.text.TextUtils; - -import java.awt.*; -import java.awt.geom.AffineTransform; -import java.awt.geom.Arc2D; -import java.awt.geom.Rectangle2D; -import java.awt.image.BufferedImage; -import java.awt.image.ColorModel; -import java.awt.image.DataBuffer; - -public class BaseCanvas_Delegate { - // ---- delegate manager ---- - protected static DelegateManager<BaseCanvas_Delegate> sManager = - new DelegateManager<>(BaseCanvas_Delegate.class); - - // ---- delegate helper data ---- - private final static boolean[] sBoolOut = new boolean[1]; - - - // ---- delegate data ---- - protected Bitmap_Delegate mBitmap; - protected GcSnapshot mSnapshot; - - // ---- Public Helper methods ---- - - protected BaseCanvas_Delegate(Bitmap_Delegate bitmap) { - mSnapshot = GcSnapshot.createDefaultSnapshot(mBitmap = bitmap); - } - - protected BaseCanvas_Delegate() { - mSnapshot = GcSnapshot.createDefaultSnapshot(null /*image*/); - } - - /** - * Disposes of the {@link Graphics2D} stack. - */ - protected void dispose() { - mSnapshot.dispose(); - } - - /** - * Returns the current {@link Graphics2D} used to draw. - */ - public GcSnapshot getSnapshot() { - return mSnapshot; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static void nDrawBitmap(long nativeCanvas, Bitmap bitmap, float left, float top, - long nativePaintOrZero, int canvasDensity, int screenDensity, int bitmapDensity) { - // get the delegate from the native int. - Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap); - if (bitmapDelegate == null) { - return; - } - - BufferedImage image = bitmapDelegate.getImage(); - float right = left + image.getWidth(); - float bottom = top + image.getHeight(); - - drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero, - 0, 0, image.getWidth(), image.getHeight(), - (int)left, (int)top, (int)right, (int)bottom); - } - - @LayoutlibDelegate - /*package*/ static void nDrawBitmap(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) { - // get the delegate from the native int. - Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap); - if (bitmapDelegate == null) { - return; - } - - drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero, (int) srcLeft, (int) srcTop, - (int) srcRight, (int) srcBottom, (int) dstLeft, (int) dstTop, (int) dstRight, - (int) dstBottom); - } - - @LayoutlibDelegate - /*package*/ static void nDrawBitmap(long nativeCanvas, int[] colors, int offset, int stride, - final float x, final float y, int width, int height, boolean hasAlpha, - long nativePaintOrZero) { - // create a temp BufferedImage containing the content. - final BufferedImage image = new BufferedImage(width, height, - hasAlpha ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB); - image.setRGB(0, 0, width, height, colors, offset, stride); - - draw(nativeCanvas, nativePaintOrZero, true /*compositeOnly*/, false /*forceSrcMode*/, - (graphics, paint) -> { - if (paint != null && paint.isFilterBitmap()) { - graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, - RenderingHints.VALUE_INTERPOLATION_BILINEAR); - } - - graphics.drawImage(image, (int) x, (int) y, null); - }); - } - - @LayoutlibDelegate - /*package*/ static void nDrawColor(long nativeCanvas, final int color, final int mode) { - // get the delegate from the native int. - BaseCanvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return; - } - - final int w = canvasDelegate.mBitmap.getImage().getWidth(); - final int h = canvasDelegate.mBitmap.getImage().getHeight(); - draw(nativeCanvas, (graphics, paint) -> { - // reset its transform just in case - graphics.setTransform(new AffineTransform()); - - // set the color - graphics.setColor(new java.awt.Color(color, true /*alpha*/)); - - Composite composite = PorterDuffUtility.getComposite( - PorterDuffUtility.getPorterDuffMode(mode), 0xFF); - if (composite != null) { - graphics.setComposite(composite); - } - - graphics.fillRect(0, 0, w, h); - }); - } - - @LayoutlibDelegate - /*package*/ static void nDrawPaint(long nativeCanvas, long paint) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Canvas.drawPaint is not supported.", null, null /*data*/); - } - - @LayoutlibDelegate - /*package*/ static void nDrawPoint(long nativeCanvas, float x, float y, - long nativePaint) { - // TODO: need to support the attribute (e.g. stroke width) of paint - draw(nativeCanvas, nativePaint, false /*compositeOnly*/, false /*forceSrcMode*/, - (graphics, paintDelegate) -> graphics.fillRect((int)x, (int)y, 1, 1)); - } - - @LayoutlibDelegate - /*package*/ static void nDrawPoints(long nativeCanvas, float[] pts, int offset, int count, - long nativePaint) { - if (offset < 0 || count < 0 || offset + count > pts.length) { - throw new IllegalArgumentException("Invalid argument set"); - } - // ignore the last point if the count is odd (It means it is not paired). - count = (count >> 1) << 1; - for (int i = offset; i < offset + count; i += 2) { - nDrawPoint(nativeCanvas, pts[i], pts[i + 1], nativePaint); - } - } - - @LayoutlibDelegate - /*package*/ static void nDrawLine(long nativeCanvas, - final float startX, final float startY, final float stopX, final float stopY, - long paint) { - draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/, - (graphics, paintDelegate) -> graphics.drawLine((int)startX, (int)startY, (int)stopX, (int)stopY)); - } - - @LayoutlibDelegate - /*package*/ static void nDrawLines(long nativeCanvas, - final float[] pts, final int offset, final int count, - long nativePaint) { - draw(nativeCanvas, nativePaint, false /*compositeOnly*/, - false /*forceSrcMode*/, (graphics, paintDelegate) -> { - for (int i = 0; i < count; i += 4) { - graphics.drawLine((int) pts[i + offset], (int) pts[i + offset + 1], - (int) pts[i + offset + 2], (int) pts[i + offset + 3]); - } - }); - } - - @LayoutlibDelegate - /*package*/ static void nDrawRect(long nativeCanvas, - final float left, final float top, final float right, final float bottom, long paint) { - - draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/, - (graphics, paintDelegate) -> { - int style = paintDelegate.getStyle(); - - // draw - if (style == Paint.Style.FILL.nativeInt || - style == Paint.Style.FILL_AND_STROKE.nativeInt) { - graphics.fillRect((int)left, (int)top, - (int)(right-left), (int)(bottom-top)); - } - - if (style == Paint.Style.STROKE.nativeInt || - style == Paint.Style.FILL_AND_STROKE.nativeInt) { - graphics.drawRect((int)left, (int)top, - (int)(right-left), (int)(bottom-top)); - } - }); - } - - @LayoutlibDelegate - /*package*/ static void nDrawOval(long nativeCanvas, final float left, - final float top, final float right, final float bottom, long paint) { - if (right > left && bottom > top) { - draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/, - (graphics, paintDelegate) -> { - int style = paintDelegate.getStyle(); - - // draw - if (style == Paint.Style.FILL.nativeInt || - style == Paint.Style.FILL_AND_STROKE.nativeInt) { - graphics.fillOval((int)left, (int)top, - (int)(right - left), (int)(bottom - top)); - } - - if (style == Paint.Style.STROKE.nativeInt || - style == Paint.Style.FILL_AND_STROKE.nativeInt) { - graphics.drawOval((int)left, (int)top, - (int)(right - left), (int)(bottom - top)); - } - }); - } - } - - @LayoutlibDelegate - /*package*/ static void nDrawCircle(long nativeCanvas, - float cx, float cy, float radius, long paint) { - nDrawOval(nativeCanvas, - cx - radius, cy - radius, cx + radius, cy + radius, - paint); - } - - @LayoutlibDelegate - /*package*/ static void nDrawArc(long nativeCanvas, - final float left, final float top, final float right, final float bottom, - final float startAngle, final float sweep, - final boolean useCenter, long paint) { - if (right > left && bottom > top) { - draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/, - (graphics, paintDelegate) -> { - int style = paintDelegate.getStyle(); - - Arc2D.Float arc = new Arc2D.Float( - left, top, right - left, bottom - top, - -startAngle, -sweep, - useCenter ? Arc2D.PIE : Arc2D.OPEN); - - // draw - if (style == Paint.Style.FILL.nativeInt || - style == Paint.Style.FILL_AND_STROKE.nativeInt) { - graphics.fill(arc); - } - - if (style == Paint.Style.STROKE.nativeInt || - style == Paint.Style.FILL_AND_STROKE.nativeInt) { - graphics.draw(arc); - } - }); - } - } - - @LayoutlibDelegate - /*package*/ static void nDrawRoundRect(long nativeCanvas, - final float left, final float top, final float right, final float bottom, - final float rx, final float ry, long paint) { - draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/, - (graphics, paintDelegate) -> { - int style = paintDelegate.getStyle(); - - // draw - if (style == Paint.Style.FILL.nativeInt || - style == Paint.Style.FILL_AND_STROKE.nativeInt) { - graphics.fillRoundRect( - (int)left, (int)top, - (int)(right - left), (int)(bottom - top), - 2 * (int)rx, 2 * (int)ry); - } - - if (style == Paint.Style.STROKE.nativeInt || - style == Paint.Style.FILL_AND_STROKE.nativeInt) { - graphics.drawRoundRect( - (int)left, (int)top, - (int)(right - left), (int)(bottom - top), - 2 * (int)rx, 2 * (int)ry); - } - }); - } - - @LayoutlibDelegate - public static void nDrawPath(long nativeCanvas, long path, long paint) { - final Path_Delegate pathDelegate = Path_Delegate.getDelegate(path); - if (pathDelegate == null) { - return; - } - - draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/, - (graphics, paintDelegate) -> { - Shape shape = pathDelegate.getJavaShape(); - Rectangle2D bounds = shape.getBounds2D(); - if (bounds.isEmpty()) { - // Apple JRE 1.6 doesn't like drawing empty shapes. - // http://b.android.com/178278 - - if (pathDelegate.isEmpty()) { - // This means that the path doesn't have any lines or curves so - // nothing to draw. - return; - } - - // The stroke width is not consider for the size of the bounds so, - // for example, a horizontal line, would be considered as an empty - // rectangle. - // If the strokeWidth is not 0, we use it to consider the size of the - // path as well. - float strokeWidth = paintDelegate.getStrokeWidth(); - if (strokeWidth <= 0.0f) { - return; - } - bounds.setRect(bounds.getX(), bounds.getY(), - Math.max(strokeWidth, bounds.getWidth()), - Math.max(strokeWidth, bounds.getHeight())); - } - - int style = paintDelegate.getStyle(); - - if (style == Paint.Style.FILL.nativeInt || - style == Paint.Style.FILL_AND_STROKE.nativeInt) { - graphics.fill(shape); - } - - if (style == Paint.Style.STROKE.nativeInt || - style == Paint.Style.FILL_AND_STROKE.nativeInt) { - graphics.draw(shape); - } - }); - } - - @LayoutlibDelegate - /*package*/ static void nDrawRegion(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 nDrawNinePatch(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 nDrawBitmapMatrix(long nCanvas, Bitmap bitmap, - long nMatrix, long nPaint) { - // get the delegate from the native int. - BaseCanvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas); - if (canvasDelegate == null) { - return; - } - - // get the delegate from the native int, which can be null - Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nPaint); - - // get the delegate from the native int. - Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap); - if (bitmapDelegate == null) { - return; - } - - final BufferedImage image = getImageToDraw(bitmapDelegate, paintDelegate, sBoolOut); - - Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix); - if (matrixDelegate == null) { - return; - } - - final AffineTransform mtx = matrixDelegate.getAffineTransform(); - - canvasDelegate.getSnapshot().draw((graphics, paint) -> { - if (paint != null && paint.isFilterBitmap()) { - graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, - RenderingHints.VALUE_INTERPOLATION_BILINEAR); - } - - //FIXME add support for canvas, screen and bitmap densities. - graphics.drawImage(image, mtx, null); - }, paintDelegate, true /*compositeOnly*/, false /*forceSrcMode*/); - } - - @LayoutlibDelegate - /*package*/ static void nDrawBitmapMesh(long nCanvas, Bitmap bitmap, - int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors, - int colorOffset, long nPaint) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Canvas.drawBitmapMesh is not supported.", null, null /*data*/); - } - - @LayoutlibDelegate - /*package*/ static void nDrawVertices(long nCanvas, int mode, int n, - float[] verts, int vertOffset, - float[] texs, int texOffset, - int[] colors, int colorOffset, - short[] indices, int indexOffset, - int indexCount, long nPaint) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Canvas.drawVertices is not supported.", null, null /*data*/); - } - - @LayoutlibDelegate - /*package*/ static void nDrawText(long nativeCanvas, char[] text, int index, int count, - float startX, float startY, int flags, long paint, long typeface) { - drawText(nativeCanvas, text, index, count, startX, startY, (flags & 1) != 0, - paint, typeface); - } - - @LayoutlibDelegate - /*package*/ static void nDrawText(long nativeCanvas, String text, - int start, int end, float x, float y, final int flags, long paint, - long typeface) { - int count = end - start; - char[] buffer = TemporaryBuffer.obtain(count); - TextUtils.getChars(text, start, end, buffer, 0); - - nDrawText(nativeCanvas, buffer, 0, count, x, y, flags, paint, typeface); - } - - @LayoutlibDelegate - /*package*/ static void nDrawTextRun(long nativeCanvas, String text, - int start, int end, int contextStart, int contextEnd, - float x, float y, boolean isRtl, long paint, long typeface) { - int count = end - start; - char[] buffer = TemporaryBuffer.obtain(count); - TextUtils.getChars(text, start, end, buffer, 0); - - drawText(nativeCanvas, buffer, 0, count, x, y, isRtl, paint, typeface); - } - - @LayoutlibDelegate - /*package*/ static void nDrawTextRun(long nativeCanvas, char[] text, - int start, int count, int contextStart, int contextCount, - float x, float y, boolean isRtl, long paint, long typeface) { - drawText(nativeCanvas, text, start, count, x, y, isRtl, paint, typeface); - } - - @LayoutlibDelegate - /*package*/ static void nDrawTextOnPath(long nativeCanvas, - char[] text, int index, - int count, long path, - float hOffset, - float vOffset, int bidiFlags, - long paint, long typeface) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Canvas.drawTextOnPath is not supported.", null, null /*data*/); - } - - @LayoutlibDelegate - /*package*/ static void nDrawTextOnPath(long nativeCanvas, - String text, long path, - float hOffset, - float vOffset, - int bidiFlags, long paint, - long typeface) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Canvas.drawTextOnPath is not supported.", null, null /*data*/); - } - - // ---- Private delegate/helper methods ---- - - /** - * Executes a {@link GcSnapshot.Drawable} with a given canvas and paint. - * <p>Note that the drawable may actually be executed several times if there are - * layers involved (see {@link #saveLayer(RectF, Paint_Delegate, int)}. - */ - private static void draw(long nCanvas, long nPaint, boolean compositeOnly, boolean forceSrcMode, - GcSnapshot.Drawable drawable) { - // get the delegate from the native int. - BaseCanvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas); - if (canvasDelegate == null) { - return; - } - - // get the paint which can be null if nPaint is 0; - Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nPaint); - - canvasDelegate.getSnapshot().draw(drawable, paintDelegate, compositeOnly, forceSrcMode); - } - - /** - * Executes a {@link GcSnapshot.Drawable} with a given canvas. No paint object will be provided - * to {@link GcSnapshot.Drawable#draw(Graphics2D, Paint_Delegate)}. - * <p>Note that the drawable may actually be executed several times if there are - * layers involved (see {@link #saveLayer(RectF, Paint_Delegate, int)}. - */ - private static void draw(long nCanvas, GcSnapshot.Drawable drawable) { - // get the delegate from the native int. - BaseCanvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas); - if (canvasDelegate == null) { - return; - } - - canvasDelegate.mSnapshot.draw(drawable); - } - - private static void drawText(long nativeCanvas, final char[] text, final int index, - final int count, final float startX, final float startY, final boolean isRtl, - long paint, final long typeface) { - - draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/, - (graphics, paintDelegate) -> { - // WARNING: the logic in this method is similar to Paint_Delegate.measureText. - // Any change to this method should be reflected in Paint.measureText - - // assert that the typeface passed is actually the one stored in paint. - assert (typeface == paintDelegate.mNativeTypeface); - - // Paint.TextAlign indicates how the text is positioned relative to X. - // LEFT is the default and there's nothing to do. - float x = startX; - int limit = index + count; - if (paintDelegate.getTextAlign() != Paint.Align.LEFT.nativeInt) { - RectF bounds = - paintDelegate.measureText(text, index, count, null, 0, isRtl); - float m = bounds.right - bounds.left; - if (paintDelegate.getTextAlign() == Paint.Align.CENTER.nativeInt) { - x -= m / 2; - } else if (paintDelegate.getTextAlign() == Paint.Align.RIGHT.nativeInt) { - x -= m; - } - } - - new BidiRenderer(graphics, paintDelegate, text).setRenderLocation(x, - startY).renderText(index, limit, isRtl, null, 0, true); - }); - } - - private static void drawBitmap(long nativeCanvas, Bitmap_Delegate bitmap, - long nativePaintOrZero, final int sleft, final int stop, final int sright, - final int sbottom, final int dleft, final int dtop, final int dright, - final int dbottom) { - // get the delegate from the native int. - BaseCanvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return; - } - - // get the paint, which could be null if the int is 0 - Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nativePaintOrZero); - - final BufferedImage image = getImageToDraw(bitmap, paintDelegate, sBoolOut); - - draw(nativeCanvas, nativePaintOrZero, true /*compositeOnly*/, sBoolOut[0], - (graphics, paint) -> { - if (paint != null && paint.isFilterBitmap()) { - graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, - RenderingHints.VALUE_INTERPOLATION_BILINEAR); - } - - //FIXME add support for canvas, screen and bitmap densities. - graphics.drawImage(image, dleft, dtop, dright, dbottom, sleft, stop, sright, - sbottom, null); - }); - } - - /** - * Returns a BufferedImage ready for drawing, based on the bitmap and paint delegate. - * The image returns, through a 1-size boolean array, whether the drawing code should - * use a SRC composite no matter what the paint says. - * - * @param bitmap the bitmap - * @param paint the paint that will be used to draw - * @param forceSrcMode whether the composite will have to be SRC - * @return the image to draw - */ - private static BufferedImage getImageToDraw(Bitmap_Delegate bitmap, Paint_Delegate paint, - boolean[] forceSrcMode) { - BufferedImage image = bitmap.getImage(); - forceSrcMode[0] = false; - - // if the bitmap config is alpha_8, then we erase all color value from it - // before drawing it or apply the texture from the shader if present. - if (bitmap.getConfig() == Bitmap.Config.ALPHA_8) { - Shader_Delegate shader = paint.getShader(); - java.awt.Paint javaPaint = null; - if (shader instanceof BitmapShader_Delegate) { - javaPaint = shader.getJavaPaint(); - } - - fixAlpha8Bitmap(image, javaPaint); - } 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: - // - override the composite to be SRC. This can only be used if the composite - // was going to be SRC or SRC_OVER in the first place - // - Create a different bitmap to draw in which all the alpha channel values is set - // to 0xFF. - if (paint != null) { - PorterDuff.Mode mode = PorterDuff.intToMode(paint.getPorterDuffMode()); - - forceSrcMode[0] = mode == PorterDuff.Mode.SRC_OVER || mode == PorterDuff.Mode.SRC; - } - - // if we can't force SRC mode, then create a temp bitmap of TYPE_RGB - if (!forceSrcMode[0]) { - image = Bitmap_Delegate.createCopy(image, BufferedImage.TYPE_INT_RGB, 0xFF); - } - } - - return image; - } - - /** - * This method will apply the correct color to the passed "only alpha" image. Colors on the - * passed image will be destroyed. - * If the passed javaPaint is null, the color will be set to 0. If a paint is passed, it will - * be used to obtain the color that will be applied. - * <p/> - * This will destroy the passed image color channel. - */ - private static void fixAlpha8Bitmap(final BufferedImage image, - @Nullable java.awt.Paint javaPaint) { - int w = image.getWidth(); - int h = image.getHeight(); - - DataBuffer texture = null; - if (javaPaint != null) { - PaintContext context = javaPaint.createContext(ColorModel.getRGBdefault(), null, null, - new AffineTransform(), null); - texture = context.getRaster(0, 0, w, h).getDataBuffer(); - } - - int[] argb = new int[w * h]; - image.getRGB(0, 0, image.getWidth(), image.getHeight(), argb, 0, image.getWidth()); - - final int length = argb.length; - for (int i = 0; i < length; i++) { - argb[i] &= 0xFF000000; - if (texture != null) { - argb[i] |= texture.getElem(i) & 0x00FFFFFF; - } - } - - image.setRGB(0, 0, w, h, argb, 0, w); - } - - protected int save(int saveFlags) { - // get the current save count - int count = mSnapshot.size(); - - mSnapshot = mSnapshot.save(saveFlags); - - // return the old save count - return count; - } - - protected int saveLayerAlpha(RectF rect, int alpha, int saveFlags) { - Paint_Delegate paint = new Paint_Delegate(); - paint.setAlpha(alpha); - return saveLayer(rect, paint, saveFlags); - } - - protected int saveLayer(RectF rect, Paint_Delegate paint, int saveFlags) { - // get the current save count - int count = mSnapshot.size(); - - mSnapshot = mSnapshot.saveLayer(rect, paint, saveFlags); - - // return the old save count - return count; - } - - /** - * Restores the {@link GcSnapshot} to <var>saveCount</var> - * @param saveCount the saveCount - */ - protected void restoreTo(int saveCount) { - mSnapshot = mSnapshot.restoreTo(saveCount); - } - - /** - * Restores the top {@link GcSnapshot} - */ - protected void restore() { - mSnapshot = mSnapshot.restore(); - } - - protected boolean clipRect(float left, float top, float right, float bottom, int regionOp) { - return mSnapshot.clipRect(left, top, right, bottom, regionOp); - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java b/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java deleted file mode 100644 index c6827a3c9c5f..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java +++ /dev/null @@ -1,325 +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 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; -import java.awt.font.FontRenderContext; -import java.awt.font.GlyphVector; -import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; - -/** - * 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. - */ -@SuppressWarnings("deprecation") -public class BidiRenderer { - private static String JAVA_VENDOR = System.getProperty("java.vendor"); - - private static class ScriptRun { - int start; - int limit; - boolean isRtl; - int scriptCode; - Font font; - - public ScriptRun(int start, int limit, boolean isRtl) { - this.start = start; - this.limit = limit; - this.isRtl = isRtl; - this.scriptCode = UScript.INVALID_CODE; - } - } - - private final Graphics2D mGraphics; - private final Paint_Delegate mPaint; - private char[] mText; - // This List can contain nulls. A null font implies that the we weren't able to load the font - // properly. So, if we encounter a situation where we try to use that font, log a warning. - private List<Font> mFonts; - // Bounds of the text drawn so far. - private RectF mBounds; - private float mBaseline; - - /** - * @param graphics May be null. - * @param paint The Paint to use to get the fonts. Should not be null. - * @param text Unidirectional text. Should not be null. - */ - public BidiRenderer(Graphics2D graphics, Paint_Delegate paint, char[] text) { - assert (paint != null); - mGraphics = graphics; - mPaint = paint; - mText = text; - mFonts = new ArrayList<Font>(paint.getFonts().size()); - for (FontInfo fontInfo : paint.getFonts()) { - if (fontInfo == null) { - mFonts.add(null); - continue; - } - mFonts.add(fontInfo.mFont); - } - mBounds = new RectF(); - } - - /** - * - * @param x The x-coordinate of the left edge of where the text should be drawn on the given - * graphics. - * @param y The y-coordinate at which to draw the text on the given mGraphics. - * - */ - public BidiRenderer setRenderLocation(float x, float y) { - mBounds = new RectF(x, y, x, y); - mBaseline = y; - return this; - } - - /** - * Perform Bidi Analysis on the text and then render it. - * <p/> - * To skip the analysis and render unidirectional text, see {@link - * #renderText(int, int, boolean, float[], int, boolean)} - */ - public RectF renderText(int start, int limit, int bidiFlags, float[] advances, - int advancesIndex, boolean draw) { - Bidi bidi = new Bidi(mText, start, null, 0, limit - start, getIcuFlags(bidiFlags)); - for (int i = 0; i < bidi.countRuns(); i++) { - BidiRun visualRun = bidi.getVisualRun(i); - boolean isRtl = visualRun.getDirection() == Bidi.RTL; - renderText(visualRun.getStart(), visualRun.getLimit(), isRtl, advances, - advancesIndex, draw); - } - return mBounds; - } - - /** - * Render unidirectional text. - * <p/> - * This method can also be used to measure the width of the text without actually drawing it. - * <p/> - * @param start index of the first character - * @param limit index of the first character that should not be rendered. - * @param isRtl is the text right-to-left - * @param advances If not null, then advances for each character to be rendered are returned - * here. - * @param advancesIndex index into advances from where the advances need to be filled. - * @param draw If true and {@code graphics} is not null, draw the rendered text on the graphics - * at the given co-ordinates - * @return A rectangle specifying the bounds of the text drawn. - */ - public RectF renderText(int start, int limit, boolean isRtl, float[] advances, - int advancesIndex, boolean draw) { - // We break the text into scripts and then select font based on it and then render each of - // the script runs. - for (ScriptRun run : getScriptRuns(mText, start, limit, isRtl, mFonts)) { - int flag = Font.LAYOUT_NO_LIMIT_CONTEXT | Font.LAYOUT_NO_START_CONTEXT; - flag |= isRtl ? Font.LAYOUT_RIGHT_TO_LEFT : Font.LAYOUT_LEFT_TO_RIGHT; - renderScript(run.start, run.limit, run.font, flag, advances, advancesIndex, draw); - advancesIndex += run.limit - run.start; - } - return mBounds; - } - - /** - * Render a script run to the right of the bounds passed. Use the preferred font to render as - * much as possible. This also implements a fallback mechanism to render characters that cannot - * be drawn using the preferred font. - */ - private void renderScript(int start, int limit, Font preferredFont, int flag, - float[] advances, int advancesIndex, boolean draw) { - if (mFonts.size() == 0 || preferredFont == null) { - return; - } - - while (start < limit) { - boolean foundFont = false; - int canDisplayUpTo = preferredFont.canDisplayUpTo(mText, start, limit); - if (canDisplayUpTo == -1) { - // We can draw all characters in the text. - render(start, limit, preferredFont, flag, advances, advancesIndex, draw); - return; - } - if (canDisplayUpTo > start) { - // We can draw something. - render(start, canDisplayUpTo, preferredFont, flag, advances, advancesIndex, draw); - advancesIndex += canDisplayUpTo - start; - start = canDisplayUpTo; - } - - // The current character cannot be drawn with the preferred font. Cycle through all the - // fonts to check which one can draw it. - int charCount = Character.isHighSurrogate(mText[start]) ? 2 : 1; - for (Font font : mFonts) { - if (font == null) { - logFontWarning(); - continue; - } - canDisplayUpTo = font.canDisplayUpTo(mText, start, start + charCount); - if (canDisplayUpTo == -1) { - render(start, start+charCount, font, flag, advances, advancesIndex, draw); - start += charCount; - advancesIndex += charCount; - foundFont = true; - break; - } - } - if (!foundFont) { - // No font can display this char. Use the preferred font. The char will most - // probably appear as a box or a blank space. We could, probably, use some - // heuristics and break the character into the base character and diacritics and - // then draw it, but it's probably not worth the effort. - render(start, start + charCount, preferredFont, flag, advances, advancesIndex, - draw); - start += charCount; - advancesIndex += charCount; - } - } - } - - private static void logFontWarning() { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_BROKEN, - "Some fonts could not be loaded. The rendering may not be perfect. " + - "Try running the IDE with JRE 7.", null, null); - } - - /** - * Renders the text to the right of the bounds with the given font. - * @param font The font to render the text with. - */ - private void render(int start, int limit, Font font, int flag, float[] advances, - int advancesIndex, boolean draw) { - - FontRenderContext frc; - if (mGraphics != null) { - frc = mGraphics.getFontRenderContext(); - } else { - frc = Toolkit.getDefaultToolkit().getFontMetrics(font).getFontRenderContext(); - - // Metrics obtained this way don't have anti-aliasing set. So, - // we create a new FontRenderContext with anti-aliasing set. - AffineTransform transform = font.getTransform(); - if (mPaint.isAntiAliased() && - // Workaround for http://b.android.com/211659 - (transform.getScaleX() <= 9.9 || - !"JetBrains s.r.o".equals(JAVA_VENDOR))) { - frc = new FontRenderContext(transform, true, frc.usesFractionalMetrics()); - } - } - GlyphVector gv = font.layoutGlyphVector(frc, mText, start, limit, flag); - int ng = gv.getNumGlyphs(); - int[] ci = gv.getGlyphCharIndices(0, ng, null); - if (advances != null) { - for (int i = 0; i < ng; i++) { - int adv_idx = advancesIndex + ci[i]; - advances[adv_idx] += gv.getGlyphMetrics(i).getAdvanceX(); - } - } - if (draw && mGraphics != null) { - mGraphics.drawGlyphVector(gv, mBounds.right, mBaseline); - } - - // Update the bounds. - Rectangle2D awtBounds = gv.getLogicalBounds(); - RectF bounds = awtRectToAndroidRect(awtBounds, mBounds.right, mBaseline); - // If the width of the bounds is zero, no text had been drawn earlier. Hence, use the - // coordinates from the bounds as an offset. - if (Math.abs(mBounds.right - mBounds.left) == 0) { - mBounds = bounds; - } else { - mBounds.union(bounds); - } - } - - // --- Static helper methods --- - - private static RectF awtRectToAndroidRect(Rectangle2D awtRec, float offsetX, float offsetY) { - float left = (float) awtRec.getX(); - float top = (float) awtRec.getY(); - float right = (float) (left + awtRec.getWidth()); - float bottom = (float) (top + awtRec.getHeight()); - RectF androidRect = new RectF(left, top, right, bottom); - androidRect.offset(offsetX, offsetY); - return androidRect; - } - - /* package */ static List<ScriptRun> getScriptRuns(char[] text, int start, int limit, - boolean isRtl, List<Font> fonts) { - LinkedList<ScriptRun> scriptRuns = new LinkedList<ScriptRun>(); - - int count = limit - start; - UScriptRun uScriptRun = new UScriptRun(text, start, count); - while (uScriptRun.next()) { - int scriptStart = uScriptRun.getScriptStart(); - int scriptLimit = uScriptRun.getScriptLimit(); - ScriptRun run = new ScriptRun(scriptStart, scriptLimit, isRtl); - run.scriptCode = uScriptRun.getScriptCode(); - setScriptFont(text, run, fonts); - scriptRuns.add(run); - } - - return scriptRuns; - } - - // TODO: Replace this method with one which returns the font based on the scriptCode. - private static void setScriptFont(char[] text, ScriptRun run, - List<Font> fonts) { - for (Font font : fonts) { - if (font == null) { - logFontWarning(); - continue; - } - if (font.canDisplayUpTo(text, run.start, run.limit) == -1) { - run.font = font; - return; - } - } - run.font = fonts.get(0); - } - - private static int getIcuFlags(int bidiFlag) { - switch (bidiFlag) { - case Paint.BIDI_LTR: - case Paint.BIDI_FORCE_LTR: - return Bidi.DIRECTION_LEFT_TO_RIGHT; - case Paint.BIDI_RTL: - case Paint.BIDI_FORCE_RTL: - return Bidi.DIRECTION_RIGHT_TO_LEFT; - case Paint.BIDI_DEFAULT_LTR: - return Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT; - case Paint.BIDI_DEFAULT_RTL: - return Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT; - default: - assert false; - return Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT; - } - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java deleted file mode 100644 index 8bd2a7acafdc..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.ninepatch.NinePatchChunk; -import com.android.resources.Density; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.annotation.Nullable; -import com.android.layoutlib.bridge.util.NinePatchInputStream; -import android.graphics.BitmapFactory.Options; -import android.graphics.Bitmap_Delegate.BitmapCreateFlags; - -import java.io.FileDescriptor; -import java.io.IOException; -import java.io.InputStream; -import java.util.EnumSet; -import java.util.Set; - -/** - * Delegate implementing the native methods of android.graphics.BitmapFactory - * - * Through the layoutlib_create tool, the original native methods of BitmapFactory have been - * replaced by calls to methods of the same name in this delegate class. - * - * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager} - * around to map int to instance of the delegate. - * - */ -/*package*/ class BitmapFactory_Delegate { - - // ------ Native Delegates ------ - - @LayoutlibDelegate - /*package*/ static Bitmap nativeDecodeStream(InputStream is, byte[] storage, - @Nullable Rect padding, @Nullable Options opts) { - Bitmap bm = null; - - Density density = Density.MEDIUM; - Set<BitmapCreateFlags> bitmapCreateFlags = EnumSet.of(BitmapCreateFlags.MUTABLE); - if (opts != null) { - density = Density.getEnum(opts.inDensity); - if (opts.inPremultiplied) { - bitmapCreateFlags.add(BitmapCreateFlags.PREMULTIPLIED); - } - opts.inScaled = false; - } - - try { - if (is instanceof NinePatchInputStream) { - NinePatchInputStream npis = (NinePatchInputStream) is; - npis.disableFakeMarkSupport(); - - // load the bitmap as a nine patch - com.android.ninepatch.NinePatch ninePatch = com.android.ninepatch.NinePatch.load( - npis, true /*is9Patch*/, false /*convert*/); - - // get the bitmap and chunk objects. - bm = Bitmap_Delegate.createBitmap(ninePatch.getImage(), bitmapCreateFlags, - density); - NinePatchChunk chunk = ninePatch.getChunk(); - - // put the chunk in the bitmap - bm.setNinePatchChunk(NinePatch_Delegate.serialize(chunk)); - - if (padding != null) { - // read the padding - int[] paddingArray = chunk.getPadding(); - padding.left = paddingArray[0]; - padding.top = paddingArray[1]; - padding.right = paddingArray[2]; - padding.bottom = paddingArray[3]; - } - } else { - // load the bitmap directly. - bm = Bitmap_Delegate.createBitmap(is, bitmapCreateFlags, density); - } - } catch (IOException e) { - Bridge.getLog().error(null, "Failed to load image", e, null); - } - - return bm; - } - - @LayoutlibDelegate - /*package*/ static Bitmap nativeDecodeFileDescriptor(FileDescriptor fd, - Rect padding, Options opts) { - opts.inBitmap = null; - return null; - } - - @LayoutlibDelegate - /*package*/ static Bitmap nativeDecodeAsset(long asset, Rect padding, Options opts) { - opts.inBitmap = null; - return null; - } - - @LayoutlibDelegate - /*package*/ static Bitmap nativeDecodeByteArray(byte[] data, int offset, - int length, Options opts) { - opts.inBitmap = null; - return null; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeIsSeekable(FileDescriptor fd) { - return true; - } - - /** - * Set the newly decoded bitmap's density based on the Options. - * - * Copied from {@link BitmapFactory#setDensityFromOptions(Bitmap, Options)}. - */ - @LayoutlibDelegate - /*package*/ static void setDensityFromOptions(Bitmap outputBitmap, Options opts) { - if (outputBitmap == null || opts == null) return; - - final int density = opts.inDensity; - if (density != 0) { - outputBitmap.setDensity(density); - final int targetDensity = opts.inTargetDensity; - if (targetDensity == 0 || density == targetDensity || density == opts.inScreenDensity) { - return; - } - - // --- Change from original implementation begins --- - // LayoutLib doesn't scale the nine patch when decoding it. Hence, don't change the - // density of the source bitmap in case of ninepatch. - - if (opts.inScaled) { - // --- Change from original implementation ends. --- - outputBitmap.setDensity(targetDensity); - } - } else if (opts.inBitmap != null) { - // bitmap was reused, ensure density is reset - outputBitmap.setDensity(Bitmap.getDefaultDensity()); - } - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java deleted file mode 100644 index 4914a48f20cd..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.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.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 - * - * Through the layoutlib_create tool, the original native methods of BitmapShader 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 BitmapShader class. - * - * Because this extends {@link Shader_Delegate}, there's no need to use a {@link DelegateManager}, - * as all the Shader classes will be added to the manager owned by {@link Shader_Delegate}. - * - * @see Shader_Delegate - * - */ -public class BitmapShader_Delegate extends Shader_Delegate { - - // ---- delegate data ---- - private java.awt.Paint mJavaPaint; - - // ---- Public Helper methods ---- - - @Override - public java.awt.Paint getJavaPaint() { - return mJavaPaint; - } - - @Override - public boolean isSupported() { - return true; - } - - @Override - public String getSupportMessage() { - // no message since isSupported returns true; - return null; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static long nativeCreate(long nativeMatrix, Bitmap androidBitmap, - int shaderTileModeX, int shaderTileModeY) { - Bitmap_Delegate bitmap = Bitmap_Delegate.getDelegate(androidBitmap); - if (bitmap == null) { - return 0; - } - - BitmapShader_Delegate newDelegate = new BitmapShader_Delegate(nativeMatrix, - bitmap.getImage(), - Shader_Delegate.getTileMode(shaderTileModeX), - Shader_Delegate.getTileMode(shaderTileModeY)); - return sManager.addNewDelegate(newDelegate); - } - - // ---- Private delegate/helper methods ---- - - private BitmapShader_Delegate(long matrix, BufferedImage image, - TileMode tileModeX, TileMode tileModeY) { - super(matrix); - mJavaPaint = new BitmapShaderPaint(image, tileModeX, tileModeY); - } - - private class BitmapShaderPaint implements java.awt.Paint { - private final BufferedImage mImage; - private final TileMode mTileModeX; - private final TileMode mTileModeY; - - BitmapShaderPaint(BufferedImage image, - TileMode tileModeX, TileMode tileModeY) { - mImage = image; - mTileModeX = tileModeX; - mTileModeY = tileModeY; - } - - @Override - public PaintContext createContext(ColorModel colorModel, Rectangle deviceBounds, - Rectangle2D userBounds, AffineTransform xform, RenderingHints hints) { - AffineTransform canvasMatrix; - try { - canvasMatrix = xform.createInverse(); - } catch (NoninvertibleTransformException e) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE, - "Unable to inverse matrix in BitmapShader", e, null /*data*/); - canvasMatrix = new AffineTransform(); - } - - AffineTransform localMatrix = getLocalMatrix(); - try { - localMatrix = localMatrix.createInverse(); - } catch (NoninvertibleTransformException e) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE, - "Unable to inverse matrix in BitmapShader", e, null /*data*/); - localMatrix = new AffineTransform(); - } - - if (!colorModel.isCompatibleRaster(mImage.getRaster())) { - // Fallback to the default ARGB color model - colorModel = ColorModel.getRGBdefault(); - } - - return new BitmapShaderContext(canvasMatrix, localMatrix, colorModel); - } - - private class BitmapShaderContext implements PaintContext { - - private final AffineTransform mCanvasMatrix; - private final AffineTransform mLocalMatrix; - private final ColorModel mColorModel; - - public BitmapShaderContext( - AffineTransform canvasMatrix, - AffineTransform localMatrix, - ColorModel colorModel) { - mCanvasMatrix = canvasMatrix; - mLocalMatrix = localMatrix; - mColorModel = colorModel; - } - - @Override - public void dispose() { - } - - @Override - public ColorModel getColorModel() { - return mColorModel; - } - - @Override - public Raster getRaster(int x, int y, int w, int h) { - BufferedImage image = new BufferedImage( - mColorModel, mColorModel.createCompatibleWritableRaster(w, h), - mColorModel.isAlphaPremultiplied(), null); - - int[] data = new int[w*h]; - - int index = 0; - float[] pt1 = new float[2]; - float[] pt2 = new float[2]; - for (int iy = 0 ; iy < h ; iy++) { - for (int ix = 0 ; ix < w ; ix++) { - // handle the canvas transform - pt1[0] = x + ix; - pt1[1] = y + iy; - mCanvasMatrix.transform(pt1, 0, pt2, 0, 1); - - // handle the local matrix. - pt1[0] = pt2[0]; - pt1[1] = pt2[1]; - mLocalMatrix.transform(pt1, 0, pt2, 0, 1); - - data[index++] = getColor(pt2[0], pt2[1]); - } - } - - image.setRGB(0 /*startX*/, 0 /*startY*/, w, h, data, 0 /*offset*/, w /*scansize*/); - - return image.getRaster(); - } - } - - /** - * Returns a color for an arbitrary point. - */ - private int getColor(float fx, float fy) { - int x = getCoordinate(Math.round(fx), mImage.getWidth(), mTileModeX); - int y = getCoordinate(Math.round(fy), mImage.getHeight(), mTileModeY); - - return mImage.getRGB(x, y); - } - - private int getCoordinate(int i, int size, TileMode mode) { - if (i < 0) { - switch (mode) { - case CLAMP: - i = 0; - break; - case REPEAT: - i = size - 1 - (-i % size); - break; - case MIRROR: - // this is the same as the positive side, just make the value positive - // first. - i = -i; - int count = i / size; - i = i % size; - - if ((count % 2) == 1) { - i = size - 1 - i; - } - break; - } - } else if (i >= size) { - switch (mode) { - case CLAMP: - i = size - 1; - break; - case REPEAT: - i = i % size; - break; - case MIRROR: - int count = i / size; - i = i % size; - - if ((count % 2) == 1) { - i = size - 1 - i; - } - break; - } - } - - return i; - } - - - @Override - public int getTransparency() { - return java.awt.Paint.TRANSLUCENT; - } - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java deleted file mode 100644 index 0064537943ab..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java +++ /dev/null @@ -1,736 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.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; -import android.graphics.Bitmap.Config; -import android.os.Parcel; - -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.Buffer; -import java.util.Arrays; -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 - * - * Through the layoutlib_create tool, the original native methods of Bitmap 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 Bitmap class. - * - * @see DelegateManager - * - */ -public final class Bitmap_Delegate { - - - public enum BitmapCreateFlags { - NONE, PREMULTIPLIED, MUTABLE - } - - // ---- delegate manager ---- - private static final DelegateManager<Bitmap_Delegate> sManager = - new DelegateManager<>(Bitmap_Delegate.class); - private static long sFinalizer = -1; - - // ---- delegate helper data ---- - - // ---- delegate data ---- - private final Config mConfig; - private final BufferedImage mImage; - private boolean mHasAlpha = true; - private boolean mHasMipMap = false; // TODO: check the default. - private boolean mIsPremultiplied = true; - private int mGenerationId = 0; - - - // ---- Public Helper methods ---- - - /** - * Returns the native delegate associated to a given an int referencing a {@link Bitmap} object. - */ - public static Bitmap_Delegate getDelegate(long native_bitmap) { - return sManager.getDelegate(native_bitmap); - } - - @Nullable - public static Bitmap_Delegate getDelegate(@Nullable Bitmap bitmap) { - return bitmap == null ? null : getDelegate(bitmap.getNativeInstance()); - } - - /** - * Creates and returns a {@link Bitmap} initialized with the given file content. - * - * @param input the file from which to read the bitmap content - * @param isMutable whether the bitmap is mutable - * @param density the density associated with the bitmap - * - * @see Bitmap#isMutable() - * @see Bitmap#getDensity() - */ - public static Bitmap createBitmap(File input, boolean isMutable, Density density) - throws IOException { - return createBitmap(input, getPremultipliedBitmapCreateFlags(isMutable), density); - } - - /** - * Creates and returns a {@link Bitmap} initialized with the given file content. - * - * @param input the file from which to read the bitmap content - * @param density the density associated with the bitmap - * - * @see Bitmap#isPremultiplied() - * @see Bitmap#isMutable() - * @see Bitmap#getDensity() - */ - private static Bitmap createBitmap(File input, Set<BitmapCreateFlags> createFlags, - Density density) throws IOException { - // create a delegate with the content of the file. - 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()); - } - - /** - * Creates and returns a {@link Bitmap} initialized with the given stream content. - * - * @param input the stream from which to read the bitmap content - * @param isMutable whether the bitmap is mutable - * @param density the density associated with the bitmap - * - * @see Bitmap#isMutable() - * @see Bitmap#getDensity() - */ - public static Bitmap createBitmap(InputStream input, boolean isMutable, Density density) - throws IOException { - return createBitmap(input, getPremultipliedBitmapCreateFlags(isMutable), density); - } - - /** - * Creates and returns a {@link Bitmap} initialized with the given stream content. - * - * @param input the stream from which to read the bitmap content - * @param density the density associated with the bitmap - * - * @see Bitmap#isPremultiplied() - * @see Bitmap#isMutable() - * @see Bitmap#getDensity() - */ - public static Bitmap createBitmap(InputStream input, Set<BitmapCreateFlags> createFlags, - Density density) throws IOException { - // create a delegate with the content of the stream. - Bitmap_Delegate delegate = new Bitmap_Delegate(ImageIO.read(input), Config.ARGB_8888); - - return createBitmap(delegate, createFlags, density.getDpiValue()); - } - - /** - * Creates and returns a {@link Bitmap} initialized with the given {@link BufferedImage} - * - * @param image the bitmap content - * @param isMutable whether the bitmap is mutable - * @param density the density associated with the bitmap - * - * @see Bitmap#isMutable() - * @see Bitmap#getDensity() - */ - public static Bitmap createBitmap(BufferedImage image, boolean isMutable, Density density) { - return createBitmap(image, getPremultipliedBitmapCreateFlags(isMutable), density); - } - - /** - * Creates and returns a {@link Bitmap} initialized with the given {@link BufferedImage} - * - * @param image the bitmap content - * @param density the density associated with the bitmap - * - * @see Bitmap#isPremultiplied() - * @see Bitmap#isMutable() - * @see Bitmap#getDensity() - */ - public static Bitmap createBitmap(BufferedImage image, Set<BitmapCreateFlags> createFlags, - Density density) { - // create a delegate with the given image. - Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ARGB_8888); - - return createBitmap(delegate, createFlags, density.getDpiValue()); - } - - private static int getBufferedImageType() { - return BufferedImage.TYPE_INT_ARGB; - } - - /** - * Returns the {@link BufferedImage} used by the delegate of the given {@link Bitmap}. - */ - public BufferedImage getImage() { - return mImage; - } - - /** - * Returns the Android bitmap config. Note that this not the config of the underlying - * Java2D bitmap. - */ - public Config getConfig() { - return mConfig; - } - - /** - * Returns the hasAlpha rendering hint - * @return true if the bitmap alpha should be used at render time - */ - public boolean hasAlpha() { - return mHasAlpha && mConfig != Config.RGB_565; - } - - /** - * Update the generationId. - * - * @see Bitmap#getGenerationId() - */ - public void change() { - mGenerationId++; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static Bitmap nativeCreate(int[] colors, int offset, int stride, int width, - int height, int nativeConfig, boolean isMutable, @Nullable float[] xyzD50, - @Nullable ColorSpace.Rgb.TransferParameters p) { - int imageType = getBufferedImageType(); - - // create the image - BufferedImage image = new BufferedImage(width, height, imageType); - - if (colors != null) { - image.setRGB(0, 0, width, height, colors, offset, stride); - } - - // create a delegate with the content of the stream. - Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.nativeToConfig(nativeConfig)); - - return createBitmap(delegate, getPremultipliedBitmapCreateFlags(isMutable), - Bitmap.getDefaultDensity()); - } - - @LayoutlibDelegate - /*package*/ static Bitmap nativeCopy(long srcBitmap, int nativeConfig, boolean isMutable) { - Bitmap_Delegate srcBmpDelegate = sManager.getDelegate(srcBitmap); - if (srcBmpDelegate == null) { - return null; - } - - BufferedImage srcImage = srcBmpDelegate.getImage(); - - int width = srcImage.getWidth(); - int height = srcImage.getHeight(); - - int imageType = getBufferedImageType(); - - // create the image - BufferedImage image = new BufferedImage(width, height, imageType); - - // copy the source image into the image. - int[] argb = new int[width * height]; - srcImage.getRGB(0, 0, width, height, argb, 0, width); - image.setRGB(0, 0, width, height, argb, 0, width); - - // create a delegate with the content of the stream. - Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.nativeToConfig(nativeConfig)); - - return createBitmap(delegate, getPremultipliedBitmapCreateFlags(isMutable), - Bitmap.getDefaultDensity()); - } - - @LayoutlibDelegate - /*package*/ static Bitmap nativeCopyAshmem(long nativeSrcBitmap) { - // Unused method; no implementation provided. - assert false; - return null; - } - - @LayoutlibDelegate - /*package*/ static Bitmap nativeCopyAshmemConfig(long nativeSrcBitmap, int nativeConfig) { - // Unused method; no implementation provided. - assert false; - return null; - } - - @LayoutlibDelegate - /*package*/ static long nativeGetNativeFinalizer() { - synchronized (Bitmap_Delegate.class) { - if (sFinalizer == -1) { - sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(sManager::removeJavaReferenceFor); - } - return sFinalizer; - } - } - - @LayoutlibDelegate - /*package*/ static boolean nativeRecycle(long nativeBitmap) { - // In our case reycle() is a no-op. We will let the finalizer to dispose the bitmap. - return true; - } - - @LayoutlibDelegate - /*package*/ static void nativeReconfigure(long nativeBitmap, int width, int height, - int config, boolean isPremultiplied) { - Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, - "Bitmap.reconfigure() is not supported", null /*data*/); - } - - @LayoutlibDelegate - /*package*/ static boolean nativeCompress(long nativeBitmap, int format, int quality, - OutputStream stream, byte[] tempStorage) { - Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, - "Bitmap.compress() is not supported", null /*data*/); - return true; - } - - @LayoutlibDelegate - /*package*/ static void nativeErase(long nativeBitmap, int color) { - // get the delegate from the native int. - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return; - } - - BufferedImage image = delegate.mImage; - - Graphics2D g = image.createGraphics(); - try { - g.setColor(new java.awt.Color(color, true)); - - g.fillRect(0, 0, image.getWidth(), image.getHeight()); - } finally { - g.dispose(); - } - } - - @LayoutlibDelegate - /*package*/ static int nativeRowBytes(long nativeBitmap) { - // get the delegate from the native int. - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return 0; - } - - return delegate.mImage.getWidth(); - } - - @LayoutlibDelegate - /*package*/ static int nativeConfig(long nativeBitmap) { - // get the delegate from the native int. - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return 0; - } - - return delegate.mConfig.nativeInt; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeHasAlpha(long nativeBitmap) { - // get the delegate from the native int. - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - return delegate == null || delegate.mHasAlpha; - - } - - @LayoutlibDelegate - /*package*/ static boolean nativeHasMipMap(long nativeBitmap) { - // get the delegate from the native int. - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - return delegate == null || delegate.mHasMipMap; - - } - - @LayoutlibDelegate - /*package*/ static int nativeGetPixel(long nativeBitmap, int x, int y) { - // get the delegate from the native int. - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return 0; - } - - return delegate.mImage.getRGB(x, y); - } - - @LayoutlibDelegate - /*package*/ static void nativeGetPixels(long nativeBitmap, int[] pixels, int offset, - int stride, int x, int y, int width, int height) { - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return; - } - - delegate.getImage().getRGB(x, y, width, height, pixels, offset, stride); - } - - - @LayoutlibDelegate - /*package*/ static void nativeSetPixel(long nativeBitmap, int x, int y, int color) { - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return; - } - - delegate.getImage().setRGB(x, y, color); - } - - @LayoutlibDelegate - /*package*/ static void nativeSetPixels(long nativeBitmap, int[] colors, int offset, - int stride, int x, int y, int width, int height) { - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return; - } - - delegate.getImage().setRGB(x, y, width, height, colors, offset, stride); - } - - @LayoutlibDelegate - /*package*/ static void nativeCopyPixelsToBuffer(long nativeBitmap, Buffer dst) { - // FIXME implement native delegate - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Bitmap.copyPixelsToBuffer is not supported.", null, null /*data*/); - } - - @LayoutlibDelegate - /*package*/ static void nativeCopyPixelsFromBuffer(long nb, Buffer src) { - // FIXME implement native delegate - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Bitmap.copyPixelsFromBuffer is not supported.", null, null /*data*/); - } - - @LayoutlibDelegate - /*package*/ static int nativeGenerationId(long nativeBitmap) { - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return 0; - } - - return delegate.mGenerationId; - } - - @LayoutlibDelegate - /*package*/ static Bitmap nativeCreateFromParcel(Parcel p) { - // This is only called by Bitmap.CREATOR (Parcelable.Creator<Bitmap>), which is only - // used during aidl call so really this should not be called. - Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, - "AIDL is not suppored, and therefore Bitmaps cannot be created from parcels.", - null /*data*/); - return null; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeWriteToParcel(long nativeBitmap, boolean isMutable, - int density, Parcel p) { - // This is only called when sending a bitmap through aidl, so really this should not - // be called. - Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, - "AIDL is not suppored, and therefore Bitmaps cannot be written to parcels.", - null /*data*/); - return false; - } - - @LayoutlibDelegate - /*package*/ static Bitmap nativeExtractAlpha(long nativeBitmap, long nativePaint, - int[] offsetXY) { - Bitmap_Delegate bitmap = sManager.getDelegate(nativeBitmap); - if (bitmap == null) { - return null; - } - - // get the paint which can be null if nativePaint is 0. - Paint_Delegate paint = Paint_Delegate.getDelegate(nativePaint); - - if (paint != null && paint.getMaskFilter() != null) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_MASKFILTER, - "MaskFilter not supported in Bitmap.extractAlpha", - null, null /*data*/); - } - - int alpha = paint != null ? paint.getAlpha() : 0xFF; - BufferedImage image = createCopy(bitmap.getImage(), BufferedImage.TYPE_INT_ARGB, alpha); - - // create the delegate. The actual Bitmap config is only an alpha channel - Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ALPHA_8); - - // the density doesn't matter, it's set by the Java method. - return createBitmap(delegate, EnumSet.of(BitmapCreateFlags.MUTABLE), - Density.DEFAULT_DENSITY /*density*/); - } - - @LayoutlibDelegate - /*package*/ static boolean nativeIsPremultiplied(long nativeBitmap) { - // get the delegate from the native int. - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - return delegate != null && delegate.mIsPremultiplied; - - } - - @LayoutlibDelegate - /*package*/ static void nativeSetPremultiplied(long nativeBitmap, boolean isPremul) { - // get the delegate from the native int. - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return; - } - - delegate.mIsPremultiplied = isPremul; - } - - @LayoutlibDelegate - /*package*/ static void nativeSetHasAlpha(long nativeBitmap, boolean hasAlpha, - boolean isPremul) { - // get the delegate from the native int. - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return; - } - - delegate.mHasAlpha = hasAlpha; - } - - @LayoutlibDelegate - /*package*/ static void nativeSetHasMipMap(long nativeBitmap, boolean hasMipMap) { - // get the delegate from the native int. - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return; - } - - delegate.mHasMipMap = hasMipMap; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeSameAs(long nb0, long nb1) { - Bitmap_Delegate delegate1 = sManager.getDelegate(nb0); - if (delegate1 == null) { - return false; - } - - Bitmap_Delegate delegate2 = sManager.getDelegate(nb1); - if (delegate2 == null) { - return false; - } - - BufferedImage image1 = delegate1.getImage(); - BufferedImage image2 = delegate2.getImage(); - if (delegate1.mConfig != delegate2.mConfig || - image1.getWidth() != image2.getWidth() || - image1.getHeight() != image2.getHeight()) { - return false; - } - - // get the internal data - int w = image1.getWidth(); - int h = image2.getHeight(); - int[] argb1 = new int[w*h]; - int[] argb2 = new int[w*h]; - - image1.getRGB(0, 0, w, h, argb1, 0, w); - image2.getRGB(0, 0, w, h, argb2, 0, w); - - // compares - if (delegate1.mConfig == Config.ALPHA_8) { - // in this case we have to manually compare the alpha channel as the rest is garbage. - final int length = w*h; - for (int i = 0 ; i < length ; i++) { - if ((argb1[i] & 0xFF000000) != (argb2[i] & 0xFF000000)) { - return false; - } - } - return true; - } - - return Arrays.equals(argb1, argb2); - } - - @LayoutlibDelegate - /*package*/ static int nativeGetAllocationByteCount(long nativeBitmap) { - // get the delegate from the native int. - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return 0; - } - return nativeRowBytes(nativeBitmap) * delegate.mImage.getHeight(); - - } - - @LayoutlibDelegate - /*package*/ static void nativePrepareToDraw(long nativeBitmap) { - // do nothing as Bitmap_Delegate does not have caches - } - - @LayoutlibDelegate - /*package*/ static Bitmap nativeCopyPreserveInternalConfig(long nativeBitmap) { - Bitmap_Delegate srcBmpDelegate = sManager.getDelegate(nativeBitmap); - if (srcBmpDelegate == null) { - return null; - } - - BufferedImage srcImage = srcBmpDelegate.getImage(); - - // create the image - BufferedImage image = new BufferedImage(srcImage.getColorModel(), srcImage.copyData(null), - srcImage.isAlphaPremultiplied(), null); - - // create a delegate with the content of the stream. - Bitmap_Delegate delegate = new Bitmap_Delegate(image, srcBmpDelegate.getConfig()); - - return createBitmap(delegate, EnumSet.of(BitmapCreateFlags.NONE), - Bitmap.getDefaultDensity()); - } - - @LayoutlibDelegate - /*package*/ static Bitmap nativeCreateHardwareBitmap(GraphicBuffer buffer) { - Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, - "Bitmap.nativeCreateHardwareBitmap() is not supported", null /*data*/); - return null; - } - - @LayoutlibDelegate - /*package*/ static GraphicBuffer nativeCreateGraphicBufferHandle(long nativeBitmap) { - Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, - "Bitmap.nativeCreateGraphicBufferHandle() is not supported", null /*data*/); - return null; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeIsSRGB(long nativeBitmap) { - Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, - "Color spaces are not supported", null /*data*/); - return false; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeGetColorSpace(long nativePtr, float[] xyz, float[] params) { - Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, - "Color spaces are not supported", null /*data*/); - return false; - } - - @LayoutlibDelegate - /*package*/ static void nativeCopyColorSpace(long srcBitmap, long dstBitmap) { - Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, - "Color spaces are not supported", null /*data*/); - } - - // ---- Private delegate/helper methods ---- - - private Bitmap_Delegate(BufferedImage image, Config config) { - mImage = image; - mConfig = config; - } - - private static Bitmap createBitmap(Bitmap_Delegate delegate, - Set<BitmapCreateFlags> createFlags, int density) { - // get its native_int - long nativeInt = sManager.addNewDelegate(delegate); - - int width = delegate.mImage.getWidth(); - int height = delegate.mImage.getHeight(); - boolean isMutable = createFlags.contains(BitmapCreateFlags.MUTABLE); - boolean isPremultiplied = createFlags.contains(BitmapCreateFlags.PREMULTIPLIED); - - // and create/return a new Bitmap with it - return new Bitmap(nativeInt, width, height, density, isMutable, - isPremultiplied, null /*ninePatchChunk*/, null /* layoutBounds */); - } - - private static Set<BitmapCreateFlags> getPremultipliedBitmapCreateFlags(boolean isMutable) { - Set<BitmapCreateFlags> createFlags = EnumSet.of(BitmapCreateFlags.PREMULTIPLIED); - if (isMutable) { - createFlags.add(BitmapCreateFlags.MUTABLE); - } - return createFlags; - } - - /** - * Creates and returns a copy of a given BufferedImage. - * <p/> - * if alpha is different than 255, then it is applied to the alpha channel of each pixel. - * - * @param image the image to copy - * @param imageType the type of the new image - * @param alpha an optional alpha modifier - * @return a new BufferedImage - */ - /*package*/ static BufferedImage createCopy(BufferedImage image, int imageType, int alpha) { - int w = image.getWidth(); - int h = image.getHeight(); - - BufferedImage result = new BufferedImage(w, h, imageType); - - int[] argb = new int[w * h]; - image.getRGB(0, 0, image.getWidth(), image.getHeight(), argb, 0, image.getWidth()); - - if (alpha != 255) { - final int length = argb.length; - for (int i = 0 ; i < length; i++) { - int a = (argb[i] >>> 24 * alpha) / 255; - argb[i] = (a << 24) | (argb[i] & 0x00FFFFFF); - } - } - - result.setRGB(0, 0, w, h, argb, 0, w); - - return result; - } - -} diff --git a/tools/layoutlib/bridge/src/android/graphics/BlendComposite.java b/tools/layoutlib/bridge/src/android/graphics/BlendComposite.java deleted file mode 100644 index 5cc964aee722..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/BlendComposite.java +++ /dev/null @@ -1,287 +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.graphics; - -import java.awt.Composite; -import java.awt.CompositeContext; -import java.awt.RenderingHints; -import java.awt.image.ColorModel; -import java.awt.image.DataBuffer; -import java.awt.image.Raster; -import java.awt.image.WritableRaster; - -/* - * (non-Javadoc) - * The class is adapted from a demo tool for Blending Modes written by - * Romain Guy (romainguy@android.com). The tool is available at - * http://www.curious-creature.org/2006/09/20/new-blendings-modes-for-java2d/ - * - * This class has been adapted for applying color filters. When applying color filters, the src - * image should not extend beyond the dest image, but in our implementation of the filters, it does. - * To compensate for the effect, we recompute the alpha value of the src image before applying - * the color filter as it should have been applied. - */ -public final class BlendComposite implements Composite { - public enum BlendingMode { - MULTIPLY(), - SCREEN(), - DARKEN(), - LIGHTEN(), - OVERLAY(), - ADD(); - - private final BlendComposite mComposite; - - BlendingMode() { - mComposite = new BlendComposite(this); - } - - BlendComposite getBlendComposite() { - return mComposite; - } - } - - private float alpha; - private BlendingMode mode; - - private BlendComposite(BlendingMode mode) { - this(mode, 1.0f); - } - - private BlendComposite(BlendingMode mode, float alpha) { - this.mode = mode; - setAlpha(alpha); - } - - public static BlendComposite getInstance(BlendingMode mode) { - return mode.getBlendComposite(); - } - - public static BlendComposite getInstance(BlendingMode mode, float alpha) { - if (alpha > 0.9999f) { - return getInstance(mode); - } - return new BlendComposite(mode, alpha); - } - - public float getAlpha() { - return alpha; - } - - public BlendingMode getMode() { - return mode; - } - - private void setAlpha(float alpha) { - if (alpha < 0.0f || alpha > 1.0f) { - assert false : "alpha must be comprised between 0.0f and 1.0f"; - alpha = Math.min(alpha, 1.0f); - alpha = Math.max(alpha, 0.0f); - } - - this.alpha = alpha; - } - - @Override - public int hashCode() { - return Float.floatToIntBits(alpha) * 31 + mode.ordinal(); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof BlendComposite)) { - return false; - } - - BlendComposite bc = (BlendComposite) obj; - - return mode == bc.mode && alpha == bc.alpha; - } - - public CompositeContext createContext(ColorModel srcColorModel, - ColorModel dstColorModel, - RenderingHints hints) { - return new BlendingContext(this); - } - - private static final class BlendingContext implements CompositeContext { - private final Blender blender; - private final BlendComposite composite; - - private BlendingContext(BlendComposite composite) { - this.composite = composite; - this.blender = Blender.getBlenderFor(composite); - } - - public void dispose() { - } - - public void compose(Raster src, Raster dstIn, WritableRaster dstOut) { - if (src.getSampleModel().getDataType() != DataBuffer.TYPE_INT || - dstIn.getSampleModel().getDataType() != DataBuffer.TYPE_INT || - dstOut.getSampleModel().getDataType() != DataBuffer.TYPE_INT) { - throw new IllegalStateException( - "Source and destination must store pixels as INT."); - } - - int width = Math.min(src.getWidth(), dstIn.getWidth()); - int height = Math.min(src.getHeight(), dstIn.getHeight()); - - float alpha = composite.getAlpha(); - - int[] srcPixel = new int[4]; - int[] dstPixel = new int[4]; - int[] result = new int[4]; - int[] srcPixels = new int[width]; - int[] dstPixels = new int[width]; - - for (int y = 0; y < height; y++) { - dstIn.getDataElements(0, y, width, 1, dstPixels); - if (alpha != 0) { - src.getDataElements(0, y, width, 1, srcPixels); - for (int x = 0; x < width; x++) { - // pixels are stored as INT_ARGB - // our arrays are [R, G, B, A] - int pixel = srcPixels[x]; - srcPixel[0] = (pixel >> 16) & 0xFF; - srcPixel[1] = (pixel >> 8) & 0xFF; - srcPixel[2] = (pixel ) & 0xFF; - srcPixel[3] = (pixel >> 24) & 0xFF; - - pixel = dstPixels[x]; - dstPixel[0] = (pixel >> 16) & 0xFF; - dstPixel[1] = (pixel >> 8) & 0xFF; - dstPixel[2] = (pixel ) & 0xFF; - dstPixel[3] = (pixel >> 24) & 0xFF; - - // ---- Modified from original ---- - // recompute src pixel for transparency. - srcPixel[3] *= dstPixel[3] / 0xFF; - // ---- Modification ends ---- - - result = blender.blend(srcPixel, dstPixel, result); - - // mixes the result with the opacity - if (alpha == 1) { - dstPixels[x] = (result[3] & 0xFF) << 24 | - (result[0] & 0xFF) << 16 | - (result[1] & 0xFF) << 8 | - result[2] & 0xFF; - } else { - dstPixels[x] = - ((int) (dstPixel[3] + (result[3] - dstPixel[3]) * alpha) & 0xFF) << 24 | - ((int) (dstPixel[0] + (result[0] - dstPixel[0]) * alpha) & 0xFF) << 16 | - ((int) (dstPixel[1] + (result[1] - dstPixel[1]) * alpha) & 0xFF) << 8 | - (int) (dstPixel[2] + (result[2] - dstPixel[2]) * alpha) & 0xFF; - } - - } - } - dstOut.setDataElements(0, y, width, 1, dstPixels); - } - } - } - - private static abstract class Blender { - public abstract int[] blend(int[] src, int[] dst, int[] result); - - public static Blender getBlenderFor(BlendComposite composite) { - switch (composite.getMode()) { - case ADD: - return new Blender() { - @Override - public int[] blend(int[] src, int[] dst, int[] result) { - for (int i = 0; i < 4; i++) { - result[i] = Math.min(255, src[i] + dst[i]); - } - return result; - } - }; - case DARKEN: - return new Blender() { - @Override - public int[] blend(int[] src, int[] dst, int[] result) { - for (int i = 0; i < 3; i++) { - result[i] = Math.min(src[i], dst[i]); - } - result[3] = Math.min(255, src[3] + dst[3]); - return result; - } - }; - case LIGHTEN: - return new Blender() { - @Override - public int[] blend(int[] src, int[] dst, int[] result) { - for (int i = 0; i < 3; i++) { - result[i] = Math.max(src[i], dst[i]); - } - result[3] = Math.min(255, src[3] + dst[3]); - return result; - } - }; - case MULTIPLY: - return new Blender() { - @Override - public int[] blend(int[] src, int[] dst, int[] result) { - for (int i = 0; i < 3; i++) { - result[i] = (src[i] * dst[i]) >> 8; - } - result[3] = Math.min(255, src[3] + dst[3] - (src[3] * dst[3]) / 255); - return result; - } - }; - case OVERLAY: - return new Blender() { - @Override - public int[] blend(int[] src, int[] dst, int[] result) { - for (int i = 0; i < 3; i++) { - result[i] = dst[i] < 128 ? dst[i] * src[i] >> 7 : - 255 - ((255 - dst[i]) * (255 - src[i]) >> 7); - } - result[3] = Math.min(255, src[3] + dst[3]); - return result; - } - }; - case SCREEN: - return new Blender() { - @Override - public int[] blend(int[] src, int[] dst, int[] result) { - result[0] = 255 - ((255 - src[0]) * (255 - dst[0]) >> 8); - result[1] = 255 - ((255 - src[1]) * (255 - dst[1]) >> 8); - result[2] = 255 - ((255 - src[2]) * (255 - dst[2]) >> 8); - result[3] = Math.min(255, src[3] + dst[3]); - return result; - } - }; - default: - assert false : "Blender not implement for " + composite.getMode().name(); - - // Ignore the blend - return new Blender() { - @Override - public int[] blend(int[] src, int[] dst, int[] result) { - result[0] = dst[0]; - result[1] = dst[1]; - result[2] = dst[2]; - result[3] = dst[3]; - return result; - } - }; - } - } - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/BlurMaskFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BlurMaskFilter_Delegate.java deleted file mode 100644 index d2569c777527..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/BlurMaskFilter_Delegate.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate implementing the native methods of android.graphics.BlurMaskFilter - * - * Through the layoutlib_create tool, the original native methods of BlurMaskFilter 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 BlurMaskFilter class. - * - * Because this extends {@link MaskFilter_Delegate}, there's no need to use a - * {@link DelegateManager}, as all the Shader classes will be added to the manager - * owned by {@link MaskFilter_Delegate}. - * - * @see MaskFilter_Delegate - * - */ -public class BlurMaskFilter_Delegate extends MaskFilter_Delegate { - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - @Override - public boolean isSupported() { - return false; - } - - @Override - public String getSupportMessage() { - return "Blur Mask Filters are not supported."; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static long nativeConstructor(float radius, int style) { - BlurMaskFilter_Delegate newDelegate = new BlurMaskFilter_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java deleted file mode 100644 index 47216eec03bd..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java +++ /dev/null @@ -1,484 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.layoutlib.bridge.impl.GcSnapshot; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.annotation.Nullable; -import android.graphics.Bitmap.Config; - -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.geom.AffineTransform; - -import libcore.util.NativeAllocationRegistry_Delegate; - - -/** - * Delegate implementing the native methods of android.graphics.Canvas - * - * Through the layoutlib_create tool, the original native methods of Canvas 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 Canvas class. - * - * @see DelegateManager - * - */ -public final class Canvas_Delegate extends BaseCanvas_Delegate { - - // ---- delegate manager ---- - private static long sFinalizer = -1; - - private DrawFilter_Delegate mDrawFilter = null; - - // ---- Public Helper methods ---- - - /** - * Returns the native delegate associated to a given {@link Canvas} object. - */ - public static Canvas_Delegate getDelegate(Canvas canvas) { - return (Canvas_Delegate) sManager.getDelegate(canvas.getNativeCanvasWrapper()); - } - - /** - * Returns the native delegate associated to a given an int referencing a {@link Canvas} object. - */ - public static Canvas_Delegate getDelegate(long native_canvas) { - return (Canvas_Delegate) sManager.getDelegate(native_canvas); - } - - /** - * Returns the current {@link Graphics2D} used to draw. - */ - public GcSnapshot getSnapshot() { - return mSnapshot; - } - - /** - * Returns the {@link DrawFilter} delegate or null if none have been set. - * - * @return the delegate or null. - */ - public DrawFilter_Delegate getDrawFilter() { - return mDrawFilter; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static void nFreeCaches() { - // nothing to be done here. - } - - @LayoutlibDelegate - /*package*/ static void nFreeTextLayoutCaches() { - // nothing to be done here yet. - } - - @LayoutlibDelegate - /*package*/ static long nInitRaster(@Nullable Bitmap bitmap) { - long nativeBitmapOrZero = 0; - if (bitmap != null) { - nativeBitmapOrZero = bitmap.getNativeInstance(); - } - if (nativeBitmapOrZero > 0) { - // get the Bitmap from the int - Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(nativeBitmapOrZero); - - // create a new Canvas_Delegate with the given bitmap and return its new native int. - Canvas_Delegate newDelegate = new Canvas_Delegate(bitmapDelegate); - - return sManager.addNewDelegate(newDelegate); - } - - // create a new Canvas_Delegate and return its new native int. - Canvas_Delegate newDelegate = new Canvas_Delegate(); - - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - public static void nSetBitmap(long canvas, Bitmap bitmap) { - Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(canvas); - Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap); - if (canvasDelegate == null || bitmapDelegate==null) { - return; - } - canvasDelegate.mBitmap = bitmapDelegate; - canvasDelegate.mSnapshot = GcSnapshot.createDefaultSnapshot(bitmapDelegate); - } - - @LayoutlibDelegate - public static boolean nIsOpaque(long nativeCanvas) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return false; - } - - return canvasDelegate.mBitmap.getConfig() == Config.RGB_565; - } - - @LayoutlibDelegate - public static void nSetHighContrastText(long nativeCanvas, boolean highContrastText){} - - @LayoutlibDelegate - public static int nGetWidth(long nativeCanvas) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return 0; - } - - return canvasDelegate.mBitmap.getImage().getWidth(); - } - - @LayoutlibDelegate - public static int nGetHeight(long nativeCanvas) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return 0; - } - - return canvasDelegate.mBitmap.getImage().getHeight(); - } - - @LayoutlibDelegate - public static int nSave(long nativeCanvas, int saveFlags) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return 0; - } - - return canvasDelegate.save(saveFlags); - } - - @LayoutlibDelegate - public static int nSaveLayer(long nativeCanvas, float l, - float t, float r, float b, - long paint, int layerFlags) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return 0; - } - - Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(paint); - if (paintDelegate == null) { - return 0; - } - - return canvasDelegate.saveLayer(new RectF(l, t, r, b), - paintDelegate, layerFlags); - } - - @LayoutlibDelegate - public static int nSaveLayerAlpha(long nativeCanvas, float l, - float t, float r, float b, - int alpha, int layerFlags) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return 0; - } - - return canvasDelegate.saveLayerAlpha(new RectF(l, t, r, b), alpha, layerFlags); - } - - @LayoutlibDelegate - public static boolean nRestore(long nativeCanvas) { - // FIXME: implement throwOnUnderflow. - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return false; - } - - canvasDelegate.restore(); - return true; - } - - @LayoutlibDelegate - public static void nRestoreToCount(long nativeCanvas, int saveCount) { - // FIXME: implement throwOnUnderflow. - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return; - } - - canvasDelegate.restoreTo(saveCount); - } - - @LayoutlibDelegate - public static int nGetSaveCount(long nativeCanvas) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return 0; - } - - return canvasDelegate.getSnapshot().size(); - } - - @LayoutlibDelegate - public static void nTranslate(long nativeCanvas, float dx, float dy) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return; - } - - canvasDelegate.getSnapshot().translate(dx, dy); - } - - @LayoutlibDelegate - public static void nScale(long nativeCanvas, float sx, float sy) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return; - } - - canvasDelegate.getSnapshot().scale(sx, sy); - } - - @LayoutlibDelegate - public static void nRotate(long nativeCanvas, float degrees) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return; - } - - canvasDelegate.getSnapshot().rotate(Math.toRadians(degrees)); - } - - @LayoutlibDelegate - public static void nSkew(long nativeCanvas, float kx, float ky) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return; - } - - // get the current top graphics2D object. - GcSnapshot g = canvasDelegate.getSnapshot(); - - // get its current matrix - AffineTransform currentTx = g.getTransform(); - // get the AffineTransform for the given skew. - float[] mtx = Matrix_Delegate.getSkew(kx, ky); - AffineTransform matrixTx = Matrix_Delegate.getAffineTransform(mtx); - - // combine them so that the given matrix is applied after. - currentTx.preConcatenate(matrixTx); - - // give it to the graphics2D as a new matrix replacing all previous transform - g.setTransform(currentTx); - } - - @LayoutlibDelegate - public static void nConcat(long nCanvas, long nMatrix) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nCanvas); - if (canvasDelegate == null) { - return; - } - - Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix); - if (matrixDelegate == null) { - return; - } - - // get the current top graphics2D object. - GcSnapshot snapshot = canvasDelegate.getSnapshot(); - - // get its current matrix - AffineTransform currentTx = snapshot.getTransform(); - // get the AffineTransform of the given matrix - AffineTransform matrixTx = matrixDelegate.getAffineTransform(); - - // combine them so that the given matrix is applied after. - currentTx.concatenate(matrixTx); - - // give it to the graphics2D as a new matrix replacing all previous transform - snapshot.setTransform(currentTx); - } - - @LayoutlibDelegate - public static void nSetMatrix(long nCanvas, long nMatrix) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nCanvas); - if (canvasDelegate == null) { - return; - } - - Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix); - if (matrixDelegate == null) { - return; - } - - // get the current top graphics2D object. - GcSnapshot snapshot = canvasDelegate.getSnapshot(); - - // get the AffineTransform of the given matrix - AffineTransform matrixTx = matrixDelegate.getAffineTransform(); - - // give it to the graphics2D as a new matrix replacing all previous transform - snapshot.setTransform(matrixTx); - - if (matrixDelegate.hasPerspective()) { - assert false; - Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_AFFINE, - "android.graphics.Canvas#setMatrix(android.graphics.Matrix) only " + - "supports affine transformations.", null, null /*data*/); - } - } - - @LayoutlibDelegate - public static boolean nClipRect(long nCanvas, - float left, float top, - float right, float bottom, - int regionOp) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nCanvas); - if (canvasDelegate == null) { - return false; - } - - return canvasDelegate.clipRect(left, top, right, bottom, regionOp); - } - - @LayoutlibDelegate - public static boolean nClipPath(long nativeCanvas, - long nativePath, - int regionOp) { - Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return true; - } - - Path_Delegate pathDelegate = Path_Delegate.getDelegate(nativePath); - if (pathDelegate == null) { - return true; - } - - return canvasDelegate.mSnapshot.clip(pathDelegate.getJavaShape(), regionOp); - } - - @LayoutlibDelegate - public static void nSetDrawFilter(long nativeCanvas, long nativeFilter) { - Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return; - } - - canvasDelegate.mDrawFilter = DrawFilter_Delegate.getDelegate(nativeFilter); - - if (canvasDelegate.mDrawFilter != null && !canvasDelegate.mDrawFilter.isSupported()) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_DRAWFILTER, - canvasDelegate.mDrawFilter.getSupportMessage(), null, null /*data*/); - } - } - - @LayoutlibDelegate - public static boolean nGetClipBounds(long nativeCanvas, - Rect bounds) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return false; - } - - Rectangle rect = canvasDelegate.getSnapshot().getClip().getBounds(); - if (rect != null && !rect.isEmpty()) { - bounds.left = rect.x; - bounds.top = rect.y; - bounds.right = rect.x + rect.width; - bounds.bottom = rect.y + rect.height; - return true; - } - - return false; - } - - @LayoutlibDelegate - public static void nGetMatrix(long canvas, long matrix) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(canvas); - if (canvasDelegate == null) { - return; - } - - Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(matrix); - if (matrixDelegate == null) { - return; - } - - AffineTransform transform = canvasDelegate.getSnapshot().getTransform(); - matrixDelegate.set(Matrix_Delegate.makeValues(transform)); - } - - @LayoutlibDelegate - public static boolean nQuickReject(long nativeCanvas, long path) { - // FIXME properly implement quickReject - return false; - } - - @LayoutlibDelegate - public static boolean nQuickReject(long nativeCanvas, - float left, float top, - float right, float bottom) { - // FIXME properly implement quickReject - return false; - } - - @LayoutlibDelegate - /*package*/ static long nGetNativeFinalizer() { - synchronized (Canvas_Delegate.class) { - if (sFinalizer == -1) { - sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(nativePtr -> { - Canvas_Delegate delegate = Canvas_Delegate.getDelegate(nativePtr); - if (delegate != null) { - delegate.dispose(); - } - sManager.removeJavaReferenceFor(nativePtr); - }); - } - } - return sFinalizer; - } - - private Canvas_Delegate(Bitmap_Delegate bitmap) { - super(bitmap); - } - - private Canvas_Delegate() { - super(); - } -} - diff --git a/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java deleted file mode 100644 index cb013b60a06c..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import java.awt.Graphics2D; - -/** - * Delegate implementing the native methods of android.graphics.ColorFilter - * - * Through the layoutlib_create tool, the original native methods of ColorFilter 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 ColorFilter class. - * - * This also serve as a base class for all ColorFilter delegate classes. - * - * @see DelegateManager - * - */ -public abstract class ColorFilter_Delegate { - - // ---- delegate manager ---- - protected static final DelegateManager<ColorFilter_Delegate> sManager = - new DelegateManager<ColorFilter_Delegate>(ColorFilter_Delegate.class); - - // ---- delegate helper data ---- - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - public static ColorFilter_Delegate getDelegate(long nativeShader) { - return sManager.getDelegate(nativeShader); - } - - public abstract String getSupportMessage(); - - public boolean isSupported() { - return false; - } - - public void applyFilter(Graphics2D g, int width, int height) { - // This should never be called directly. If supported, the sub class should override this. - assert false; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static void nSafeUnref(long native_instance) { - sManager.removeJavaReferenceFor(native_instance); - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java deleted file mode 100644 index 67394847fa44..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate implementing the native methods of android.graphics.ColorMatrixColorFilter - * - * Through the layoutlib_create tool, the original native methods of ColorMatrixColorFilter 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 ColorMatrixColorFilter class. - * - * Because this extends {@link ColorFilter_Delegate}, there's no need to use a - * {@link DelegateManager}, as all the Shader classes will be added to the manager - * owned by {@link ColorFilter_Delegate}. - * - * @see ColorFilter_Delegate - * - */ -public class ColorMatrixColorFilter_Delegate extends ColorFilter_Delegate { - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - @Override - public String getSupportMessage() { - return "ColorMatrix Color Filters are not supported."; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static long nativeColorMatrixFilter(float[] array) { - ColorMatrixColorFilter_Delegate newDelegate = new ColorMatrixColorFilter_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/ComposePathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ComposePathEffect_Delegate.java deleted file mode 100644 index bc3df7d84894..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/ComposePathEffect_Delegate.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import java.awt.Stroke; - -/** - * Delegate implementing the native methods of android.graphics.ComposePathEffect - * - * Through the layoutlib_create tool, the original native methods of ComposePathEffect 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 ComposePathEffect class. - * - * Because this extends {@link PathEffect_Delegate}, there's no need to use a {@link DelegateManager}, - * as all the Shader classes will be added to the manager owned by {@link PathEffect_Delegate}. - * - * @see PathEffect_Delegate - * - */ -public class ComposePathEffect_Delegate extends PathEffect_Delegate { - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - @Override - public Stroke getStroke(Paint_Delegate paint) { - // FIXME - return null; - } - - @Override - public boolean isSupported() { - return false; - } - - @Override - public String getSupportMessage() { - return "Compose Path Effects are not supported in Layout Preview mode."; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static long nativeCreate(long outerpe, long innerpe) { - ComposePathEffect_Delegate newDelegate = new ComposePathEffect_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/ComposeShader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ComposeShader_Delegate.java deleted file mode 100644 index ab37968a1dea..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/ComposeShader_Delegate.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import java.awt.Paint; - -/** - * Delegate implementing the native methods of android.graphics.ComposeShader - * - * Through the layoutlib_create tool, the original native methods of ComposeShader 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 ComposeShader class. - * - * Because this extends {@link Shader_Delegate}, there's no need to use a {@link DelegateManager}, - * as all the Shader classes will be added to the manager owned by {@link Shader_Delegate}. - * - * @see Shader_Delegate - * - */ -public class ComposeShader_Delegate extends Shader_Delegate { - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - @Override - public Paint getJavaPaint() { - // FIXME - return null; - } - - @Override - public boolean isSupported() { - return false; - } - - @Override - public String getSupportMessage() { - return "Compose Shaders are not supported in Layout Preview mode."; - } - - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static long nativeCreate(long nativeMatrix, long native_shaderA, - long native_shaderB, int native_mode) { - // FIXME not supported yet. - ComposeShader_Delegate newDelegate = new ComposeShader_Delegate(nativeMatrix); - return sManager.addNewDelegate(newDelegate); - } - - - // ---- Private delegate/helper methods ---- - - private ComposeShader_Delegate(long nativeMatrix) { - super(nativeMatrix); - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/CornerPathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/CornerPathEffect_Delegate.java deleted file mode 100644 index 73745c3b0c00..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/CornerPathEffect_Delegate.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import java.awt.Stroke; - -/** - * Delegate implementing the native methods of android.graphics.CornerPathEffect - * - * Through the layoutlib_create tool, the original native methods of CornerPathEffect 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 CornerPathEffect class. - * - * Because this extends {@link PathEffect_Delegate}, there's no need to use a {@link DelegateManager}, - * as all the Shader classes will be added to the manager owned by {@link PathEffect_Delegate}. - * - * @see PathEffect_Delegate - * - */ -public class CornerPathEffect_Delegate extends PathEffect_Delegate { - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - @Override - public Stroke getStroke(Paint_Delegate paint) { - // FIXME - return null; - } - - @Override - public boolean isSupported() { - return false; - } - - @Override - public String getSupportMessage() { - return "Corner Path Effects are not supported in Layout Preview mode."; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static long nativeCreate(float radius) { - CornerPathEffect_Delegate newDelegate = new CornerPathEffect_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java deleted file mode 100644 index 881afded1158..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import java.awt.BasicStroke; -import java.awt.Stroke; - -/** - * Delegate implementing the native methods of android.graphics.DashPathEffect - * - * Through the layoutlib_create tool, the original native methods of DashPathEffect 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 DashPathEffect class. - * - * Because this extends {@link PathEffect_Delegate}, there's no need to use a - * {@link DelegateManager}, as all the PathEffect classes will be added to the manager owned by - * {@link PathEffect_Delegate}. - * - * @see PathEffect_Delegate - * - */ -public final class DashPathEffect_Delegate extends PathEffect_Delegate { - - // ---- delegate data ---- - - private final float[] mIntervals; - private final float mPhase; - - // ---- Public Helper methods ---- - - @Override - public Stroke getStroke(Paint_Delegate paint) { - return new BasicStroke( - paint.getStrokeWidth(), - paint.getJavaCap(), - paint.getJavaJoin(), - paint.getJavaStrokeMiter(), - mIntervals, - mPhase); - } - - @Override - public boolean isSupported() { - return true; - } - - @Override - public String getSupportMessage() { - // no message since isSupported returns true; - return null; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static long nativeCreate(float intervals[], float phase) { - DashPathEffect_Delegate newDelegate = new DashPathEffect_Delegate(intervals, phase); - return sManager.addNewDelegate(newDelegate); - } - - // ---- Private delegate/helper methods ---- - - private DashPathEffect_Delegate(float intervals[], float phase) { - mIntervals = new float[intervals.length]; - System.arraycopy(intervals, 0, mIntervals, 0, intervals.length); - mPhase = phase; - } -} - diff --git a/tools/layoutlib/bridge/src/android/graphics/DiscretePathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/DiscretePathEffect_Delegate.java deleted file mode 100644 index 46109f3018e1..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/DiscretePathEffect_Delegate.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import java.awt.Stroke; - -/** - * Delegate implementing the native methods of android.graphics.DiscretePathEffect - * - * Through the layoutlib_create tool, the original native methods of DiscretePathEffect 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 DiscretePathEffect class. - * - * Because this extends {@link PathEffect_Delegate}, there's no need to use a {@link DelegateManager}, - * as all the Shader classes will be added to the manager owned by {@link PathEffect_Delegate}. - * - * @see PathEffect_Delegate - * - */ -public class DiscretePathEffect_Delegate extends PathEffect_Delegate { - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - @Override - public Stroke getStroke(Paint_Delegate paint) { - // FIXME - return null; - } - - @Override - public boolean isSupported() { - return false; - } - - @Override - public String getSupportMessage() { - return "Discrete Path Effects are not supported in Layout Preview mode."; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static long nativeCreate(float length, float deviation) { - DiscretePathEffect_Delegate newDelegate = new DiscretePathEffect_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/DrawFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/DrawFilter_Delegate.java deleted file mode 100644 index 2e1074080bde..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/DrawFilter_Delegate.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate implementing the native methods of android.graphics.DrawFilter - * - * Through the layoutlib_create tool, the original native methods of DrawFilter 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 DrawFilter class. - * - * This also serve as a base class for all DrawFilter delegate classes. - * - * @see DelegateManager - * - */ -public abstract class DrawFilter_Delegate { - - // ---- delegate manager ---- - protected static final DelegateManager<DrawFilter_Delegate> sManager = - new DelegateManager<DrawFilter_Delegate>(DrawFilter_Delegate.class); - - // ---- delegate helper data ---- - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - public static DrawFilter_Delegate getDelegate(long nativeDrawFilter) { - return sManager.getDelegate(nativeDrawFilter); - } - - public abstract boolean isSupported(); - public abstract String getSupportMessage(); - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static void nativeDestructor(long nativeDrawFilter) { - sManager.removeJavaReferenceFor(nativeDrawFilter); - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/EmbossMaskFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/EmbossMaskFilter_Delegate.java deleted file mode 100644 index e5040ccc4b1e..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/EmbossMaskFilter_Delegate.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate implementing the native methods of android.graphics.EmbossMaskFilter - * - * Through the layoutlib_create tool, the original native methods of EmbossMaskFilter 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 EmbossMaskFilter class. - * - * Because this extends {@link MaskFilter_Delegate}, there's no need to use a - * {@link DelegateManager}, as all the Shader classes will be added to the manager - * owned by {@link MaskFilter_Delegate}. - * - * @see MaskFilter_Delegate - * - */ -public class EmbossMaskFilter_Delegate extends MaskFilter_Delegate { - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - @Override - public boolean isSupported() { - return false; - } - - @Override - public String getSupportMessage() { - return "Emboss Mask Filters are not supported."; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static long nativeConstructor(float[] direction, float ambient, - float specular, float blurRadius) { - EmbossMaskFilter_Delegate newDelegate = new EmbossMaskFilter_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - // ---- 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 deleted file mode 100644 index d8e049a990ed..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java +++ /dev/null @@ -1,523 +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.graphics; - -import com.android.ide.common.rendering.api.AssetRepository; -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.annotation.Nullable; -import android.content.res.AssetManager; -import android.content.res.BridgeAssetManager; -import android.graphics.fonts.FontVariationAxis; -import android.text.FontConfig; - -import java.awt.Font; -import java.awt.FontFormatException; -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.Scanner; -import java.util.Set; - -import static android.graphics.Typeface.RESOLVE_BY_FONT_TABLE; -import static android.graphics.Typeface_Delegate.SYSTEM_FONTS; - -/** - * Delegate implementing the native methods of android.graphics.FontFamily - * - * Through the layoutlib_create tool, the original native methods of FontFamily 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 FontFamily class. - * - * @see DelegateManager - */ -public class FontFamily_Delegate { - - public static final int DEFAULT_FONT_WEIGHT = 400; - public static final int BOLD_FONT_WEIGHT_DELTA = 300; - public static final int BOLD_FONT_WEIGHT = 700; - - private static final String FONT_SUFFIX_ITALIC = "Italic.ttf"; - private static final String FN_ALL_FONTS_LIST = "fontsInSdk.txt"; - private static final String EXTENSION_OTF = ".otf"; - - private static final int CACHE_SIZE = 10; - // The cache has a drawback that if the font file changed after the font object was created, - // we will not update it. - private static final Map<String, FontInfo> sCache = - new LinkedHashMap<String, FontInfo>(CACHE_SIZE) { - @Override - protected boolean removeEldestEntry(Map.Entry<String, FontInfo> eldest) { - return size() > CACHE_SIZE; - } - - @Override - public FontInfo put(String key, FontInfo value) { - // renew this entry. - FontInfo removed = remove(key); - super.put(key, value); - return removed; - } - }; - - /** - * A class associating {@link Font} with its metadata. - */ - private static final class FontInfo { - @Nullable - Font mFont; - int mWeight; - boolean mIsItalic; - } - - // ---- delegate manager ---- - private static final DelegateManager<FontFamily_Delegate> sManager = - new DelegateManager<FontFamily_Delegate>(FontFamily_Delegate.class); - - // ---- delegate helper data ---- - private static String sFontLocation; - private static final List<FontFamily_Delegate> sPostInitDelegate = new - ArrayList<FontFamily_Delegate>(); - private static Set<String> SDK_FONTS; - - - // ---- delegate data ---- - private List<FontInfo> mFonts = new ArrayList<FontInfo>(); - - /** - * The variant of the Font Family - compact or elegant. - * <p/> - * 0 is unspecified, 1 is compact and 2 is elegant. This needs to be kept in sync with values in - * android.graphics.FontFamily - * - * @see Paint#setElegantTextHeight(boolean) - */ - private FontVariant mVariant; - // List of runnables to process fonts after sFontLoader is initialized. - private List<Runnable> mPostInitRunnables = new ArrayList<Runnable>(); - /** @see #isValid() */ - private boolean mValid = false; - - - // ---- Public helper class ---- - - public enum FontVariant { - // The order needs to be kept in sync with android.graphics.FontFamily. - NONE, COMPACT, ELEGANT - } - - // ---- Public Helper methods ---- - - public static FontFamily_Delegate getDelegate(long nativeFontFamily) { - return sManager.getDelegate(nativeFontFamily); - } - - public static synchronized void setFontLocation(String fontLocation) { - sFontLocation = fontLocation; - // init list of bundled fonts. - File allFonts = new File(fontLocation, FN_ALL_FONTS_LIST); - // Current number of fonts is 103. Use the next round number to leave scope for more fonts - // in the future. - Set<String> allFontsList = new HashSet<String>(128); - Scanner scanner = null; - try { - scanner = new Scanner(allFonts); - while (scanner.hasNext()) { - String name = scanner.next(); - // Skip font configuration files. - if (!name.endsWith(".xml")) { - allFontsList.add(name); - } - } - } catch (FileNotFoundException e) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "Unable to load the list of fonts. Try re-installing the SDK Platform from the SDK Manager.", - e, null); - } finally { - if (scanner != null) { - scanner.close(); - } - } - SDK_FONTS = Collections.unmodifiableSet(allFontsList); - for (FontFamily_Delegate fontFamily : sPostInitDelegate) { - fontFamily.init(); - } - sPostInitDelegate.clear(); - } - - @Nullable - public Font getFont(int desiredWeight, boolean isItalic) { - FontInfo desiredStyle = new FontInfo(); - desiredStyle.mWeight = desiredWeight; - desiredStyle.mIsItalic = isItalic; - FontInfo bestFont = null; - int bestMatch = Integer.MAX_VALUE; - //noinspection ForLoopReplaceableByForEach (avoid iterator instantiation) - for (int i = 0, n = mFonts.size(); i < n; i++) { - FontInfo font = mFonts.get(i); - int match = computeMatch(font, desiredStyle); - if (match < bestMatch) { - bestMatch = match; - bestFont = font; - } - } - if (bestFont == null) { - return null; - } - if (bestMatch == 0) { - return bestFont.mFont; - } - // Derive the font as required and add it to the list of Fonts. - deriveFont(bestFont, desiredStyle); - addFont(desiredStyle); - return desiredStyle.mFont; - } - - public FontVariant getVariant() { - return mVariant; - } - - /** - * Returns if the FontFamily should contain any fonts. If this returns true and - * {@link #getFont(int, boolean)} returns an empty list, it means that an error occurred while - * loading the fonts. However, some fonts are deliberately skipped, for example they are not - * bundled with the SDK. In such a case, this method returns false. - */ - public boolean isValid() { - return mValid; - } - - private static Font loadFont(String path) { - if (path.startsWith(SYSTEM_FONTS) ) { - String relativePath = path.substring(SYSTEM_FONTS.length()); - File f = new File(sFontLocation, relativePath); - - try { - return Font.createFont(Font.TRUETYPE_FONT, f); - } catch (Exception e) { - if (path.endsWith(EXTENSION_OTF) && e instanceof FontFormatException) { - // If we aren't able to load an Open Type font, don't log a warning just yet. - // We wait for a case where font is being used. Only then we try to log the - // warning. - return null; - } - Bridge.getLog().fidelityWarning(LayoutLog.TAG_BROKEN, - String.format("Unable to load font %1$s", relativePath), - e, null); - } - } else { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Only platform fonts located in " + SYSTEM_FONTS + "can be loaded.", - null, null); - } - - return null; - } - - @Nullable - /*package*/ static String getFontLocation() { - return sFontLocation; - } - - // ---- delegate methods ---- - @LayoutlibDelegate - /*package*/ static boolean addFont(FontFamily thisFontFamily, String path, int ttcIndex, - FontVariationAxis[] axes, int weight, int italic) { - if (thisFontFamily.mBuilderPtr == 0) { - assert false : "Unable to call addFont after freezing."; - return false; - } - final FontFamily_Delegate delegate = getDelegate(thisFontFamily.mBuilderPtr); - return delegate != null && delegate.addFont(path, ttcIndex, weight, italic); - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static long nInitBuilder(String lang, int variant) { - // TODO: support lang. This is required for japanese locale. - FontFamily_Delegate delegate = new FontFamily_Delegate(); - // variant can be 0, 1 or 2. - assert variant < 3; - delegate.mVariant = FontVariant.values()[variant]; - if (sFontLocation != null) { - delegate.init(); - } else { - sPostInitDelegate.add(delegate); - } - return sManager.addNewDelegate(delegate); - } - - @LayoutlibDelegate - /*package*/ static long nCreateFamily(long builderPtr) { - return builderPtr; - } - - @LayoutlibDelegate - /*package*/ static void nUnrefFamily(long nativePtr) { - // Removing the java reference for the object doesn't mean that it's freed for garbage - // collection. Typeface_Delegate may still hold a reference for it. - sManager.removeJavaReferenceFor(nativePtr); - } - - @LayoutlibDelegate - /*package*/ static boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex, - int weight, int isItalic) { - assert false : "The only client of this method has been overridden."; - return false; - } - - @LayoutlibDelegate - /*package*/ static boolean nAddFontWeightStyle(long builderPtr, ByteBuffer font, - int ttcIndex, int weight, int isItalic) { - assert false : "The only client of this method has been overridden."; - return false; - } - - @LayoutlibDelegate - /*package*/ static void nAddAxisValue(long builderPtr, int tag, float value) { - assert false : "The only client of this method has been overridden."; - } - - static boolean addFont(long builderPtr, final String path, final int weight, - final boolean isItalic) { - final FontFamily_Delegate delegate = getDelegate(builderPtr); - int italic = isItalic ? 1 : 0; - if (delegate != null) { - if (sFontLocation == null) { - delegate.mPostInitRunnables.add(() -> delegate.addFont(path, weight, italic)); - return true; - } - return delegate.addFont(path, weight, italic); - } - return false; - } - - @LayoutlibDelegate - /*package*/ static boolean nAddFontFromAssetManager(long builderPtr, AssetManager mgr, String path, - int cookie, boolean isAsset, int ttcIndex, int weight, int isItalic) { - FontFamily_Delegate ffd = sManager.getDelegate(builderPtr); - if (ffd == null) { - return false; - } - ffd.mValid = true; - if (mgr == null) { - return false; - } - if (mgr instanceof BridgeAssetManager) { - InputStream fontStream = null; - try { - AssetRepository assetRepository = ((BridgeAssetManager) mgr).getAssetRepository(); - if (assetRepository == null) { - Bridge.getLog().error(LayoutLog.TAG_MISSING_ASSET, "Asset not found: " + path, - null); - return false; - } - if (!assetRepository.isSupported()) { - // Don't log any warnings on unsupported IDEs. - return false; - } - // Check cache - FontInfo fontInfo = sCache.get(path); - if (fontInfo != null) { - // renew the font's lease. - sCache.put(path, fontInfo); - ffd.addFont(fontInfo); - return true; - } - fontStream = isAsset ? - assetRepository.openAsset(path, AssetManager.ACCESS_STREAMING) : - assetRepository.openNonAsset(cookie, path, AssetManager.ACCESS_STREAMING); - if (fontStream == null) { - Bridge.getLog().error(LayoutLog.TAG_MISSING_ASSET, "Asset not found: " + path, - path); - return false; - } - Font font = Font.createFont(Font.TRUETYPE_FONT, fontStream); - fontInfo = new FontInfo(); - fontInfo.mFont = font; - if (weight == RESOLVE_BY_FONT_TABLE) { - fontInfo.mWeight = font.isBold() ? BOLD_FONT_WEIGHT : DEFAULT_FONT_WEIGHT; - } else { - fontInfo.mWeight = weight; - } - fontInfo.mIsItalic = isItalic == RESOLVE_BY_FONT_TABLE ? font.isItalic() : - isItalic == 1; - ffd.addFont(fontInfo); - return true; - } catch (IOException e) { - Bridge.getLog().error(LayoutLog.TAG_MISSING_ASSET, "Unable to load font " + path, e, - path); - } catch (FontFormatException e) { - if (path.endsWith(EXTENSION_OTF)) { - // otf fonts are not supported on the user's config (JRE version + OS) - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "OpenType fonts are not supported yet: " + path, null, path); - } else { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "Unable to load font " + path, e, path); - } - } finally { - if (fontStream != null) { - try { - fontStream.close(); - } catch (IOException ignored) { - } - } - } - return false; - } - // This should never happen. AssetManager is a final class (from user's perspective), and - // we've replaced every creation of AssetManager with our implementation. We create an - // exception and log it, but continue with rest of the rendering, without loading this font. - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "You have found a bug in the rendering library. Please file a bug at b.android.com.", - new RuntimeException("Asset Manager is not an instance of BridgeAssetManager"), - null); - return false; - } - - @LayoutlibDelegate - /*package*/ static void nAbort(long builderPtr) { - sManager.removeJavaReferenceFor(builderPtr); - } - - /** - * @see FontFamily#allowUnsupportedFont - */ - @LayoutlibDelegate - /*package*/ static void nAllowUnsupportedFont(long builderPtr) { - // Do nothing here as this is used for Minikin fonts - } - - // ---- private helper methods ---- - - private void init() { - for (Runnable postInitRunnable : mPostInitRunnables) { - postInitRunnable.run(); - } - mPostInitRunnables = null; - } - - private boolean addFont(final String path, int ttcIndex, int weight, int italic) { - // FIXME: support ttc fonts. Hack JRE?? - if (sFontLocation == null) { - mPostInitRunnables.add(() -> addFont(path, weight, italic)); - return true; - } - return addFont(path, weight, italic); - } - - private boolean addFont(@NonNull String path) { - return addFont(path, DEFAULT_FONT_WEIGHT, path.endsWith(FONT_SUFFIX_ITALIC) ? 1 : RESOLVE_BY_FONT_TABLE); - } - - private boolean addFont(@NonNull String path, int weight, int italic) { - if (path.startsWith(SYSTEM_FONTS) && - !SDK_FONTS.contains(path.substring(SYSTEM_FONTS.length()))) { - return mValid = false; - } - // Set valid to true, even if the font fails to load. - mValid = true; - Font font = loadFont(path); - if (font == null) { - return false; - } - FontInfo fontInfo = new FontInfo(); - fontInfo.mFont = font; - fontInfo.mWeight = weight; - fontInfo.mIsItalic = italic == RESOLVE_BY_FONT_TABLE ? font.isItalic() : italic == 1; - addFont(fontInfo); - return true; - } - - private boolean addFont(@NonNull FontInfo fontInfo) { - int weight = fontInfo.mWeight; - boolean isItalic = fontInfo.mIsItalic; - // The list is usually just two fonts big. So iterating over all isn't as bad as it looks. - // It's biggest for roboto where the size is 12. - //noinspection ForLoopReplaceableByForEach (avoid iterator instantiation) - for (int i = 0, n = mFonts.size(); i < n; i++) { - FontInfo font = mFonts.get(i); - if (font.mWeight == weight && font.mIsItalic == isItalic) { - return false; - } - } - mFonts.add(fontInfo); - return true; - } - - /** - * Compute matching metric between two styles - 0 is an exact match. - */ - private static int computeMatch(@NonNull FontInfo font1, @NonNull FontInfo font2) { - int score = Math.abs(font1.mWeight - font2.mWeight); - if (font1.mIsItalic != font2.mIsItalic) { - score += 200; - } - return score; - } - - /** - * Try to derive a font from {@code srcFont} for the style in {@code outFont}. - * <p/> - * {@code outFont} is updated to reflect the style of the derived font. - * @param srcFont the source font - * @param outFont contains the desired font style. Updated to contain the derived font and - * its style - * @return outFont - */ - @NonNull - 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) { - derivedFont = derivedFont.deriveFont(Font.BOLD); - srcWeight += BOLD_FONT_WEIGHT_DELTA; - } - // Italicize the font if required. - if (outFont.mIsItalic && !srcFont.mIsItalic) { - derivedFont = derivedFont.deriveFont(Font.ITALIC); - } else if (outFont.mIsItalic != srcFont.mIsItalic) { - // The desired font is plain, but the src font is italics. We can't convert it back. So - // we update the value to reflect the true style of the font we're deriving. - outFont.mIsItalic = srcFont.mIsItalic; - } - outFont.mFont = derivedFont; - outFont.mWeight = srcWeight; - // No need to update mIsItalics, as it's already been handled above. - return outFont; - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Gradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Gradient_Delegate.java deleted file mode 100644 index 64410e4c6a05..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/Gradient_Delegate.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import android.graphics.Shader.TileMode; - -/** - * Base class for true Gradient shader delegate. - */ -public abstract class Gradient_Delegate extends Shader_Delegate { - - protected final int[] mColors; - protected final float[] mPositions; - - @Override - public boolean isSupported() { - // all gradient shaders are supported. - return true; - } - - @Override - public String getSupportMessage() { - // all gradient shaders are supported, no need for a gradient support - return null; - } - - /** - * Creates the base shader and do some basic test on the parameters. - * - * @param nativeMatrix reference to the shader's native transformation matrix - * @param colors The colors to be distributed along the gradient line - * @param positions May be null. The relative positions [0..1] of each - * corresponding color in the colors array. If this is null, the - * the colors are distributed evenly along the gradient line. - */ - protected Gradient_Delegate(long nativeMatrix, int colors[], float positions[]) { - super(nativeMatrix); - assert colors.length >= 2 : "needs >= 2 number of colors"; - - if (positions == null) { - float spacing = 1.f / (colors.length - 1); - positions = new float[colors.length]; - positions[0] = 0.f; - positions[colors.length - 1] = 1.f; - for (int i = 1; i < colors.length - 1; i++) { - positions[i] = spacing * i; - } - } else { - assert colors.length == positions.length : - "color and position " + "arrays must be of equal length"; - } - - mColors = colors; - mPositions = positions; - } - - /** - * Base class for (Java) Gradient Paints. This handles computing the gradient colors based - * on the color and position lists, as well as the {@link TileMode} - * - */ - protected abstract static class GradientPaint implements java.awt.Paint { - private final static int GRADIENT_SIZE = 100; - - private final int[] mColors; - private final float[] mPositions; - private final TileMode mTileMode; - private int[] mGradient; - - protected GradientPaint(int[] colors, float[] positions, TileMode tileMode) { - mColors = colors; - mPositions = positions; - mTileMode = tileMode; - } - - @Override - public int getTransparency() { - return java.awt.Paint.TRANSLUCENT; - } - - /** - * Pre-computes the colors for the gradient. This must be called once before any call - * to {@link #getGradientColor(float)} - */ - protected void precomputeGradientColors() { - if (mGradient == null) { - // actually create an array with an extra size, so that we can really go - // from 0 to SIZE (100%), or currentPos in the loop below will never equal 1.0 - mGradient = new int[GRADIENT_SIZE+1]; - - int prevPos = 0; - int nextPos = 1; - for (int i = 0 ; i <= GRADIENT_SIZE ; i++) { - // compute current position - float currentPos = (float)i/GRADIENT_SIZE; - while (currentPos > mPositions[nextPos]) { - prevPos = nextPos++; - } - - float percent = (currentPos - mPositions[prevPos]) / - (mPositions[nextPos] - mPositions[prevPos]); - - mGradient[i] = computeColor(mColors[prevPos], mColors[nextPos], percent); - } - } - } - - /** - * Returns the color based on the position in the gradient. - * <var>pos</var> can be anything, even < 0 or > > 1, as the gradient - * will use {@link TileMode} value to convert it into a [0,1] value. - */ - protected int getGradientColor(float pos) { - if (pos < 0.f) { - if (mTileMode != null) { - switch (mTileMode) { - case CLAMP: - pos = 0.f; - break; - case REPEAT: - // remove the integer part to stay in the [0,1] range. - // we also need to invert the value from [-1,0] to [0, 1] - pos = pos - (float)Math.floor(pos); - break; - case MIRROR: - // this is the same as the positive side, just make the value positive - // first. - pos = Math.abs(pos); - - // get the integer and the decimal part - int intPart = (int)Math.floor(pos); - pos = pos - intPart; - // 0 -> 1 : normal order - // 1 -> 2: mirrored - // etc.. - // this means if the intpart is odd we invert - if ((intPart % 2) == 1) { - pos = 1.f - pos; - } - break; - } - } else { - pos = 0.0f; - } - } else if (pos > 1f) { - if (mTileMode != null) { - switch (mTileMode) { - case CLAMP: - pos = 1.f; - break; - case REPEAT: - // remove the integer part to stay in the [0,1] range - pos = pos - (float)Math.floor(pos); - break; - case MIRROR: - // get the integer and the decimal part - int intPart = (int)Math.floor(pos); - pos = pos - intPart; - // 0 -> 1 : normal order - // 1 -> 2: mirrored - // etc.. - // this means if the intpart is odd we invert - if ((intPart % 2) == 1) { - pos = 1.f - pos; - } - break; - } - } else { - pos = 1.0f; - } - } - - int index = (int)((pos * GRADIENT_SIZE) + .5); - - return mGradient[index]; - } - - /** - * Returns the color between c1, and c2, based on the percent of the distance - * between c1 and c2. - */ - private int computeColor(int c1, int c2, float percent) { - int a = computeChannel((c1 >> 24) & 0xFF, (c2 >> 24) & 0xFF, percent); - int r = computeChannel((c1 >> 16) & 0xFF, (c2 >> 16) & 0xFF, percent); - int g = computeChannel((c1 >> 8) & 0xFF, (c2 >> 8) & 0xFF, percent); - int b = computeChannel((c1 ) & 0xFF, (c2 ) & 0xFF, percent); - return a << 24 | r << 16 | g << 8 | b; - } - - /** - * Returns the channel value between 2 values based on the percent of the distance between - * the 2 values.. - */ - private int computeChannel(int c1, int c2, float percent) { - return c1 + (int)((percent * (c2-c1)) + .5); - } - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java deleted file mode 100644 index 0dd970350313..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate implementing the native methods of android.graphics.LightingColorFilter - * - * Through the layoutlib_create tool, the original native methods of LightingColorFilter 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 LightingColorFilter class. - * - * Because this extends {@link ColorFilter_Delegate}, there's no need to use a - * {@link DelegateManager}, as all the Shader classes will be added to the manager - * owned by {@link ColorFilter_Delegate}. - * - * @see ColorFilter_Delegate - * - */ -public class LightingColorFilter_Delegate extends ColorFilter_Delegate { - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - @Override - public String getSupportMessage() { - return "Lighting Color Filters are not supported."; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static long native_CreateLightingFilter(int mul, int add) { - LightingColorFilter_Delegate newDelegate = new LightingColorFilter_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java deleted file mode 100644 index cd4393abdf85..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.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.graphics.Shader.TileMode; - -import java.awt.image.ColorModel; - -/** - * Delegate implementing the native methods of android.graphics.LinearGradient - * - * Through the layoutlib_create tool, the original native methods of LinearGradient 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 LinearGradient class. - * - * Because this extends {@link Shader_Delegate}, there's no need to use a {@link DelegateManager}, - * as all the Shader classes will be added to the manager owned by {@link Shader_Delegate}. - * - * @see Shader_Delegate - * - */ -public final class LinearGradient_Delegate extends Gradient_Delegate { - - // ---- delegate data ---- - private java.awt.Paint mJavaPaint; - - // ---- Public Helper methods ---- - - @Override - public java.awt.Paint getJavaPaint() { - return mJavaPaint; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static long nativeCreate1(LinearGradient thisGradient, long matrix, - float x0, float y0, float x1, float y1, - int colors[], float positions[], int tileMode) { - LinearGradient_Delegate newDelegate = new LinearGradient_Delegate(matrix, x0, y0, - x1, y1, colors, positions, Shader_Delegate.getTileMode(tileMode)); - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static long nativeCreate2(LinearGradient thisGradient, long matrix, - float x0, float y0, float x1, float y1, - int color0, int color1, int tileMode) { - return nativeCreate1(thisGradient, matrix, x0, y0, x1, y1, new int[] { color0, color1}, - null /*positions*/, tileMode); - } - - // ---- Private delegate/helper methods ---- - - /** - * Create a shader that draws a linear gradient along a line. - * - * @param nativeMatrix reference to the shader's native transformation matrix - * @param x0 The x-coordinate for the start of the gradient line - * @param y0 The y-coordinate for the start of the gradient line - * @param x1 The x-coordinate for the end of the gradient line - * @param y1 The y-coordinate for the end of the gradient line - * @param colors The colors to be distributed along the gradient line - * @param positions May be null. The relative positions [0..1] of each - * corresponding color in the colors array. If this is null, the - * the colors are distributed evenly along the gradient line. - * @param tile The Shader tiling mode - */ - private LinearGradient_Delegate(long nativeMatrix, float x0, float y0, float x1, - float y1, int colors[], float positions[], TileMode tile) { - super(nativeMatrix, colors, positions); - mJavaPaint = new LinearGradientPaint(x0, y0, x1, y1, mColors, mPositions, tile); - } - - // ---- Custom Java Paint ---- - /** - * Linear Gradient (Java) Paint able to handle more than 2 points, as - * {@link java.awt.GradientPaint} only supports 2 points and does not support Android's tile - * modes. - */ - private class LinearGradientPaint extends GradientPaint { - - private final float mX0; - private final float mY0; - private final float mDx; - private final float mDy; - private final float mDSize2; - - public LinearGradientPaint(float x0, float y0, float x1, float y1, int colors[], - float positions[], TileMode tile) { - super(colors, positions, tile); - mX0 = x0; - mY0 = y0; - mDx = x1 - x0; - mDy = y1 - y0; - mDSize2 = mDx * mDx + mDy * mDy; - } - - @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) { - precomputeGradientColors(); - - java.awt.geom.AffineTransform canvasMatrix; - try { - canvasMatrix = xform.createInverse(); - } catch (java.awt.geom.NoninvertibleTransformException e) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE, - "Unable to inverse matrix in LinearGradient", e, null /*data*/); - canvasMatrix = new java.awt.geom.AffineTransform(); - } - - java.awt.geom.AffineTransform localMatrix = getLocalMatrix(); - try { - localMatrix = localMatrix.createInverse(); - } catch (java.awt.geom.NoninvertibleTransformException e) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE, - "Unable to inverse matrix in LinearGradient", e, null /*data*/); - localMatrix = new java.awt.geom.AffineTransform(); - } - - return new LinearGradientPaintContext(canvasMatrix, localMatrix, colorModel); - } - - private class LinearGradientPaintContext implements java.awt.PaintContext { - - private final java.awt.geom.AffineTransform mCanvasMatrix; - private final java.awt.geom.AffineTransform mLocalMatrix; - private final java.awt.image.ColorModel mColorModel; - - private LinearGradientPaintContext( - java.awt.geom.AffineTransform canvasMatrix, - java.awt.geom.AffineTransform localMatrix, - java.awt.image.ColorModel colorModel) { - mCanvasMatrix = canvasMatrix; - mLocalMatrix = localMatrix; - mColorModel = colorModel.hasAlpha() ? colorModel : ColorModel.getRGBdefault(); - } - - @Override - public void dispose() { - } - - @Override - public java.awt.image.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( - mColorModel, mColorModel.createCompatibleWritableRaster(w, h), - mColorModel.isAlphaPremultiplied(), null); - - int[] data = new int[w*h]; - - int index = 0; - float[] pt1 = new float[2]; - float[] pt2 = new float[2]; - for (int iy = 0 ; iy < h ; iy++) { - for (int ix = 0 ; ix < w ; ix++) { - // handle the canvas transform - pt1[0] = x + ix; - pt1[1] = y + iy; - mCanvasMatrix.transform(pt1, 0, pt2, 0, 1); - - // handle the local matrix. - pt1[0] = pt2[0]; - pt1[1] = pt2[1]; - mLocalMatrix.transform(pt1, 0, pt2, 0, 1); - - data[index++] = getColor(pt2[0], pt2[1]); - } - } - - image.setRGB(0 /*startX*/, 0 /*startY*/, w, h, data, 0 /*offset*/, w /*scansize*/); - - return image.getRaster(); - } - } - - /** - * Returns a color for an arbitrary point. - */ - private int getColor(float x, float y) { - float pos; - if (mDx == 0) { - pos = (y - mY0) / mDy; - } else if (mDy == 0) { - pos = (x - mX0) / mDx; - } else { - // find the x position on the gradient vector. - float _x = (mDx*mDy*(y-mY0) + mDy*mDy*mX0 + mDx*mDx*x) / mDSize2; - // from it get the position relative to the vector - pos = (_x - mX0) / mDx; - } - - return getGradientColor(pos); - } - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/MaskFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/MaskFilter_Delegate.java deleted file mode 100644 index e726c5982be2..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/MaskFilter_Delegate.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate implementing the native methods of android.graphics.MaskFilter - * - * Through the layoutlib_create tool, the original native methods of MaskFilter 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 MaskFilter class. - * - * This also serve as a base class for all MaskFilter delegate classes. - * - * @see DelegateManager - * - */ -public abstract class MaskFilter_Delegate { - - // ---- delegate manager ---- - protected static final DelegateManager<MaskFilter_Delegate> sManager = - new DelegateManager<MaskFilter_Delegate>(MaskFilter_Delegate.class); - - // ---- delegate helper data ---- - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - public static MaskFilter_Delegate getDelegate(long nativeShader) { - return sManager.getDelegate(nativeShader); - } - - public abstract boolean isSupported(); - public abstract String getSupportMessage(); - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static void nativeDestructor(long native_filter) { - sManager.removeJavaReferenceFor(native_filter); - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java deleted file mode 100644 index 354f9191beda..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java +++ /dev/null @@ -1,1077 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - - -import com.android.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.graphics.Matrix.ScaleToFit; - -import java.awt.geom.AffineTransform; -import java.awt.geom.NoninvertibleTransformException; - -import libcore.util.NativeAllocationRegistry_Delegate; - -/** - * Delegate implementing the native methods of android.graphics.Matrix - * - * Through the layoutlib_create tool, the original native methods of Matrix have been replaced - * by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original Matrix class. - * - * @see DelegateManager - * - */ -public final class Matrix_Delegate { - - private final static int MATRIX_SIZE = 9; - - // ---- delegate manager ---- - private static final DelegateManager<Matrix_Delegate> sManager = - new DelegateManager<Matrix_Delegate>(Matrix_Delegate.class); - private static long sFinalizer = -1; - - // ---- delegate data ---- - private float mValues[] = new float[MATRIX_SIZE]; - - // ---- Public Helper methods ---- - - public static Matrix_Delegate getDelegate(long native_instance) { - return sManager.getDelegate(native_instance); - } - - /** - * Returns an {@link AffineTransform} matching the given Matrix. - */ - public static AffineTransform getAffineTransform(Matrix m) { - Matrix_Delegate delegate = sManager.getDelegate(m.native_instance); - if (delegate == null) { - return null; - } - - return delegate.getAffineTransform(); - } - - public static boolean hasPerspective(Matrix m) { - Matrix_Delegate delegate = sManager.getDelegate(m.native_instance); - if (delegate == null) { - return false; - } - - return delegate.hasPerspective(); - } - - /** - * Sets the content of the matrix with the content of another matrix. - */ - public void set(Matrix_Delegate matrix) { - System.arraycopy(matrix.mValues, 0, mValues, 0, MATRIX_SIZE); - } - - /** - * Sets the content of the matrix with the content of another matrix represented as an array - * of values. - */ - public void set(float[] values) { - System.arraycopy(values, 0, mValues, 0, MATRIX_SIZE); - } - - /** - * Resets the matrix to be the identity matrix. - */ - public void reset() { - reset(mValues); - } - - /** - * Returns whether or not the matrix is identity. - */ - public boolean isIdentity() { - for (int i = 0, k = 0; i < 3; i++) { - for (int j = 0; j < 3; j++, k++) { - if (mValues[k] != ((i==j) ? 1 : 0)) { - return false; - } - } - } - - return true; - } - - public static float[] makeValues(AffineTransform matrix) { - float[] values = new float[MATRIX_SIZE]; - values[0] = (float) matrix.getScaleX(); - values[1] = (float) matrix.getShearX(); - values[2] = (float) matrix.getTranslateX(); - values[3] = (float) matrix.getShearY(); - values[4] = (float) matrix.getScaleY(); - values[5] = (float) matrix.getTranslateY(); - values[6] = 0.f; - values[7] = 0.f; - values[8] = 1.f; - - return values; - } - - public static Matrix_Delegate make(AffineTransform matrix) { - return new Matrix_Delegate(makeValues(matrix)); - } - - public boolean mapRect(RectF dst, RectF src) { - // array with 4 corners - float[] corners = new float[] { - src.left, src.top, - src.right, src.top, - src.right, src.bottom, - src.left, src.bottom, - }; - - // apply the transform to them. - mapPoints(corners); - - // now put the result in the rect. We take the min/max of Xs and min/max of Ys - dst.left = Math.min(Math.min(corners[0], corners[2]), Math.min(corners[4], corners[6])); - dst.right = Math.max(Math.max(corners[0], corners[2]), Math.max(corners[4], corners[6])); - - dst.top = Math.min(Math.min(corners[1], corners[3]), Math.min(corners[5], corners[7])); - dst.bottom = Math.max(Math.max(corners[1], corners[3]), Math.max(corners[5], corners[7])); - - - return (computeTypeMask() & kRectStaysRect_Mask) != 0; - } - - - /** - * Returns an {@link AffineTransform} matching the matrix. - */ - public AffineTransform getAffineTransform() { - return getAffineTransform(mValues); - } - - public boolean hasPerspective() { - return (mValues[6] != 0 || mValues[7] != 0 || mValues[8] != 1); - } - - - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static long nCreate(long native_src_or_zero) { - // create the delegate - Matrix_Delegate newDelegate = new Matrix_Delegate(); - - // copy from values if needed. - if (native_src_or_zero > 0) { - Matrix_Delegate oldDelegate = sManager.getDelegate(native_src_or_zero); - if (oldDelegate != null) { - System.arraycopy( - oldDelegate.mValues, 0, - newDelegate.mValues, 0, - MATRIX_SIZE); - } - } - - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static boolean nIsIdentity(long native_object) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - - return d.isIdentity(); - } - - @LayoutlibDelegate - /*package*/ static boolean nIsAffine(long native_object) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return true; - } - - return (d.computeTypeMask() & kPerspective_Mask) == 0; - } - - @LayoutlibDelegate - /*package*/ static boolean nRectStaysRect(long native_object) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return true; - } - - return (d.computeTypeMask() & kRectStaysRect_Mask) != 0; - } - - @LayoutlibDelegate - /*package*/ static void nReset(long native_object) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - reset(d.mValues); - } - - @LayoutlibDelegate - /*package*/ static void nSet(long native_object, long other) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - Matrix_Delegate src = sManager.getDelegate(other); - if (src == null) { - return; - } - - System.arraycopy(src.mValues, 0, d.mValues, 0, MATRIX_SIZE); - } - - @LayoutlibDelegate - /*package*/ static void nSetTranslate(long native_object, float dx, float dy) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - setTranslate(d.mValues, dx, dy); - } - - @LayoutlibDelegate - /*package*/ static void nSetScale(long native_object, float sx, float sy, - float px, float py) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - d.mValues = getScale(sx, sy, px, py); - } - - @LayoutlibDelegate - /*package*/ static void nSetScale(long native_object, float sx, float sy) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - d.mValues[0] = sx; - d.mValues[1] = 0; - d.mValues[2] = 0; - d.mValues[3] = 0; - d.mValues[4] = sy; - d.mValues[5] = 0; - d.mValues[6] = 0; - d.mValues[7] = 0; - d.mValues[8] = 1; - } - - @LayoutlibDelegate - /*package*/ static void nSetRotate(long native_object, float degrees, float px, float py) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - d.mValues = getRotate(degrees, px, py); - } - - @LayoutlibDelegate - /*package*/ static void nSetRotate(long native_object, float degrees) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - setRotate(d.mValues, degrees); - } - - @LayoutlibDelegate - /*package*/ static void nSetSinCos(long native_object, float sinValue, float cosValue, - float px, float py) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - // TODO: do it in one pass - - // translate so that the pivot is in 0,0 - setTranslate(d.mValues, -px, -py); - - // scale - d.postTransform(getRotate(sinValue, cosValue)); - // translate back the pivot - d.postTransform(getTranslate(px, py)); - } - - @LayoutlibDelegate - /*package*/ static void nSetSinCos(long native_object, float sinValue, float cosValue) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - setRotate(d.mValues, sinValue, cosValue); - } - - @LayoutlibDelegate - /*package*/ static void nSetSkew(long native_object, float kx, float ky, - float px, float py) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - d.mValues = getSkew(kx, ky, px, py); - } - - @LayoutlibDelegate - /*package*/ static void nSetSkew(long native_object, float kx, float ky) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - d.mValues[0] = 1; - d.mValues[1] = kx; - d.mValues[2] = -0; - d.mValues[3] = ky; - d.mValues[4] = 1; - d.mValues[5] = 0; - d.mValues[6] = 0; - d.mValues[7] = 0; - d.mValues[8] = 1; - } - - @LayoutlibDelegate - /*package*/ static void nSetConcat(long native_object, long a, long b) { - if (a == native_object) { - nPreConcat(native_object, b); - return; - } else if (b == native_object) { - nPostConcat(native_object, a); - return; - } - - Matrix_Delegate d = sManager.getDelegate(native_object); - Matrix_Delegate a_mtx = sManager.getDelegate(a); - Matrix_Delegate b_mtx = sManager.getDelegate(b); - if (d != null && a_mtx != null && b_mtx != null) { - multiply(d.mValues, a_mtx.mValues, b_mtx.mValues); - } - } - - @LayoutlibDelegate - /*package*/ static void nPreTranslate(long native_object, float dx, float dy) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d != null) { - d.preTransform(getTranslate(dx, dy)); - } - } - - @LayoutlibDelegate - /*package*/ static void nPreScale(long native_object, float sx, float sy, - float px, float py) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d != null) { - d.preTransform(getScale(sx, sy, px, py)); - } - } - - @LayoutlibDelegate - /*package*/ static void nPreScale(long native_object, float sx, float sy) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d != null) { - d.preTransform(getScale(sx, sy)); - } - } - - @LayoutlibDelegate - /*package*/ static void nPreRotate(long native_object, float degrees, - float px, float py) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d != null) { - d.preTransform(getRotate(degrees, px, py)); - } - } - - @LayoutlibDelegate - /*package*/ static void nPreRotate(long native_object, float degrees) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d != null) { - - double rad = Math.toRadians(degrees); - float sin = (float) Math.sin(rad); - float cos = (float) Math.cos(rad); - - d.preTransform(getRotate(sin, cos)); - } - } - - @LayoutlibDelegate - /*package*/ static void nPreSkew(long native_object, float kx, float ky, - float px, float py) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d != null) { - d.preTransform(getSkew(kx, ky, px, py)); - } - } - - @LayoutlibDelegate - /*package*/ static void nPreSkew(long native_object, float kx, float ky) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d != null) { - d.preTransform(getSkew(kx, ky)); - } - } - - @LayoutlibDelegate - /*package*/ static void nPreConcat(long native_object, long other_matrix) { - Matrix_Delegate d = sManager.getDelegate(native_object); - Matrix_Delegate other = sManager.getDelegate(other_matrix); - if (d != null && other != null) { - d.preTransform(other.mValues); - } - } - - @LayoutlibDelegate - /*package*/ static void nPostTranslate(long native_object, float dx, float dy) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d != null) { - d.postTransform(getTranslate(dx, dy)); - } - } - - @LayoutlibDelegate - /*package*/ static void nPostScale(long native_object, float sx, float sy, - float px, float py) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d != null) { - d.postTransform(getScale(sx, sy, px, py)); - } - } - - @LayoutlibDelegate - /*package*/ static void nPostScale(long native_object, float sx, float sy) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d != null) { - d.postTransform(getScale(sx, sy)); - } - } - - @LayoutlibDelegate - /*package*/ static void nPostRotate(long native_object, float degrees, - float px, float py) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d != null) { - d.postTransform(getRotate(degrees, px, py)); - } - } - - @LayoutlibDelegate - /*package*/ static void nPostRotate(long native_object, float degrees) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d != null) { - d.postTransform(getRotate(degrees)); - } - } - - @LayoutlibDelegate - /*package*/ static void nPostSkew(long native_object, float kx, float ky, - float px, float py) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d != null) { - d.postTransform(getSkew(kx, ky, px, py)); - } - } - - @LayoutlibDelegate - /*package*/ static void nPostSkew(long native_object, float kx, float ky) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d != null) { - d.postTransform(getSkew(kx, ky)); - } - } - - @LayoutlibDelegate - /*package*/ static void nPostConcat(long native_object, long other_matrix) { - Matrix_Delegate d = sManager.getDelegate(native_object); - Matrix_Delegate other = sManager.getDelegate(other_matrix); - if (d != null && other != null) { - d.postTransform(other.mValues); - } - } - - @LayoutlibDelegate - /*package*/ static boolean nSetRectToRect(long native_object, RectF src, - RectF dst, int stf) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - - if (src.isEmpty()) { - reset(d.mValues); - return false; - } - - if (dst.isEmpty()) { - d.mValues[0] = d.mValues[1] = d.mValues[2] = d.mValues[3] = d.mValues[4] = d.mValues[5] - = d.mValues[6] = d.mValues[7] = 0; - d.mValues[8] = 1; - } else { - float tx, sx = dst.width() / src.width(); - float ty, sy = dst.height() / src.height(); - boolean xLarger = false; - - if (stf != ScaleToFit.FILL.nativeInt) { - if (sx > sy) { - xLarger = true; - sx = sy; - } else { - sy = sx; - } - } - - tx = dst.left - src.left * sx; - ty = dst.top - src.top * sy; - if (stf == ScaleToFit.CENTER.nativeInt || stf == ScaleToFit.END.nativeInt) { - float diff; - - if (xLarger) { - diff = dst.width() - src.width() * sy; - } else { - diff = dst.height() - src.height() * sy; - } - - if (stf == ScaleToFit.CENTER.nativeInt) { - diff = diff / 2; - } - - if (xLarger) { - tx += diff; - } else { - ty += diff; - } - } - - d.mValues[0] = sx; - d.mValues[4] = sy; - d.mValues[2] = tx; - d.mValues[5] = ty; - d.mValues[1] = d.mValues[3] = d.mValues[6] = d.mValues[7] = 0; - - } - // shared cleanup - d.mValues[8] = 1; - return true; - } - - @LayoutlibDelegate - /*package*/ static boolean nSetPolyToPoly(long native_object, float[] src, int srcIndex, - float[] dst, int dstIndex, int pointCount) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Matrix.setPolyToPoly is not supported.", - null, null /*data*/); - return false; - } - - @LayoutlibDelegate - /*package*/ static boolean nInvert(long native_object, long inverse) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - - Matrix_Delegate inv_mtx = sManager.getDelegate(inverse); - if (inv_mtx == null) { - return false; - } - - try { - AffineTransform affineTransform = d.getAffineTransform(); - AffineTransform inverseTransform = affineTransform.createInverse(); - inv_mtx.mValues[0] = (float)inverseTransform.getScaleX(); - inv_mtx.mValues[1] = (float)inverseTransform.getShearX(); - inv_mtx.mValues[2] = (float)inverseTransform.getTranslateX(); - inv_mtx.mValues[3] = (float)inverseTransform.getScaleX(); - inv_mtx.mValues[4] = (float)inverseTransform.getShearY(); - inv_mtx.mValues[5] = (float)inverseTransform.getTranslateY(); - - return true; - } catch (NoninvertibleTransformException e) { - return false; - } - } - - @LayoutlibDelegate - /*package*/ static void nMapPoints(long native_object, float[] dst, int dstIndex, - float[] src, int srcIndex, int ptCount, boolean isPts) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - if (isPts) { - d.mapPoints(dst, dstIndex, src, srcIndex, ptCount); - } else { - d.mapVectors(dst, dstIndex, src, srcIndex, ptCount); - } - } - - @LayoutlibDelegate - /*package*/ static boolean nMapRect(long native_object, RectF dst, RectF src) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - - return d.mapRect(dst, src); - } - - @LayoutlibDelegate - /*package*/ static float nMapRadius(long native_object, float radius) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return 0.f; - } - - float[] src = new float[] { radius, 0.f, 0.f, radius }; - d.mapVectors(src, 0, src, 0, 2); - - float l1 = (float) Math.hypot(src[0], src[1]); - float l2 = (float) Math.hypot(src[2], src[3]); - return (float) Math.sqrt(l1 * l2); - } - - @LayoutlibDelegate - /*package*/ static void nGetValues(long native_object, float[] values) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - System.arraycopy(d.mValues, 0, values, 0, MATRIX_SIZE); - } - - @LayoutlibDelegate - /*package*/ static void nSetValues(long native_object, float[] values) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - System.arraycopy(values, 0, d.mValues, 0, MATRIX_SIZE); - } - - @LayoutlibDelegate - /*package*/ static boolean nEquals(long native_a, long native_b) { - Matrix_Delegate a = sManager.getDelegate(native_a); - if (a == null) { - return false; - } - - Matrix_Delegate b = sManager.getDelegate(native_b); - if (b == null) { - return false; - } - - for (int i = 0 ; i < MATRIX_SIZE ; i++) { - if (a.mValues[i] != b.mValues[i]) { - return false; - } - } - - return true; - } - - @LayoutlibDelegate - /*package*/ static long nGetNativeFinalizer() { - synchronized (Matrix_Delegate.class) { - if (sFinalizer == -1) { - sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(sManager::removeJavaReferenceFor); - } - } - return sFinalizer; - } - - // ---- Private helper methods ---- - - /*package*/ static AffineTransform getAffineTransform(float[] matrix) { - // the AffineTransform constructor takes the value in a different order - // for a matrix [ 0 1 2 ] - // [ 3 4 5 ] - // the order is 0, 3, 1, 4, 2, 5... - return new AffineTransform( - matrix[0], matrix[3], matrix[1], - matrix[4], matrix[2], matrix[5]); - } - - /** - * Reset a matrix to the identity - */ - private static void reset(float[] mtx) { - for (int i = 0, k = 0; i < 3; i++) { - for (int j = 0; j < 3; j++, k++) { - mtx[k] = ((i==j) ? 1 : 0); - } - } - } - - @SuppressWarnings("unused") - private final static int kIdentity_Mask = 0; - private final static int kTranslate_Mask = 0x01; //!< set if the matrix has translation - private final static int kScale_Mask = 0x02; //!< set if the matrix has X or Y scale - private final static int kAffine_Mask = 0x04; //!< set if the matrix skews or rotates - private final static int kPerspective_Mask = 0x08; //!< set if the matrix is in perspective - private final static int kRectStaysRect_Mask = 0x10; - @SuppressWarnings("unused") - private final static int kUnknown_Mask = 0x80; - - @SuppressWarnings("unused") - private final static int kAllMasks = kTranslate_Mask | - kScale_Mask | - kAffine_Mask | - kPerspective_Mask | - kRectStaysRect_Mask; - - // these guys align with the masks, so we can compute a mask from a variable 0/1 - @SuppressWarnings("unused") - private final static int kTranslate_Shift = 0; - @SuppressWarnings("unused") - private final static int kScale_Shift = 1; - @SuppressWarnings("unused") - private final static int kAffine_Shift = 2; - @SuppressWarnings("unused") - private final static int kPerspective_Shift = 3; - private final static int kRectStaysRect_Shift = 4; - - private int computeTypeMask() { - int mask = 0; - - if (mValues[6] != 0. || mValues[7] != 0. || mValues[8] != 1.) { - mask |= kPerspective_Mask; - } - - if (mValues[2] != 0. || mValues[5] != 0.) { - mask |= kTranslate_Mask; - } - - float m00 = mValues[0]; - float m01 = mValues[1]; - float m10 = mValues[3]; - float m11 = mValues[4]; - - if (m01 != 0. || m10 != 0.) { - mask |= kAffine_Mask; - } - - if (m00 != 1. || m11 != 1.) { - mask |= kScale_Mask; - } - - if ((mask & kPerspective_Mask) == 0) { - // map non-zero to 1 - int im00 = m00 != 0 ? 1 : 0; - int im01 = m01 != 0 ? 1 : 0; - int im10 = m10 != 0 ? 1 : 0; - int im11 = m11 != 0 ? 1 : 0; - - // record if the (p)rimary and (s)econdary diagonals are all 0 or - // all non-zero (answer is 0 or 1) - int dp0 = (im00 | im11) ^ 1; // true if both are 0 - int dp1 = im00 & im11; // true if both are 1 - int ds0 = (im01 | im10) ^ 1; // true if both are 0 - int ds1 = im01 & im10; // true if both are 1 - - // return 1 if primary is 1 and secondary is 0 or - // primary is 0 and secondary is 1 - mask |= ((dp0 & ds1) | (dp1 & ds0)) << kRectStaysRect_Shift; - } - - return mask; - } - - private Matrix_Delegate() { - reset(); - } - - private Matrix_Delegate(float[] values) { - System.arraycopy(values, 0, mValues, 0, MATRIX_SIZE); - } - - /** - * Adds the given transformation to the current Matrix - * <p/>This in effect does this = this*matrix - * @param matrix - */ - private void postTransform(float[] matrix) { - float[] tmp = new float[9]; - multiply(tmp, mValues, matrix); - mValues = tmp; - } - - /** - * Adds the given transformation to the current Matrix - * <p/>This in effect does this = matrix*this - * @param matrix - */ - private void preTransform(float[] matrix) { - float[] tmp = new float[9]; - multiply(tmp, matrix, mValues); - mValues = tmp; - } - - /** - * Apply this matrix to the array of 2D points specified by src, and write - * the transformed points into the array of points specified by dst. The - * two arrays represent their "points" as pairs of floats [x, y]. - * - * @param dst The array of dst points (x,y pairs) - * @param dstIndex The index of the first [x,y] pair of dst floats - * @param src The array of src points (x,y pairs) - * @param srcIndex The index of the first [x,y] pair of src floats - * @param pointCount The number of points (x,y pairs) to transform - */ - - private void mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex, - int pointCount) { - final int count = pointCount * 2; - - float[] tmpDest = dst; - boolean inPlace = dst == src; - if (inPlace) { - tmpDest = new float[dstIndex + count]; - } - - for (int i = 0 ; i < count ; i += 2) { - // just in case we are doing in place, we better put this in temp vars - float x = mValues[0] * src[i + srcIndex] + - mValues[1] * src[i + srcIndex + 1] + - mValues[2]; - float y = mValues[3] * src[i + srcIndex] + - mValues[4] * src[i + srcIndex + 1] + - mValues[5]; - - tmpDest[i + dstIndex] = x; - tmpDest[i + dstIndex + 1] = y; - } - - if (inPlace) { - System.arraycopy(tmpDest, dstIndex, dst, dstIndex, count); - } - } - - /** - * Apply this matrix to the array of 2D points, and write the transformed - * points back into the array - * - * @param pts The array [x0, y0, x1, y1, ...] of points to transform. - */ - - private void mapPoints(float[] pts) { - mapPoints(pts, 0, pts, 0, pts.length >> 1); - } - - private void mapVectors(float[] dst, int dstIndex, float[] src, int srcIndex, int ptCount) { - if (hasPerspective()) { - // transform the (0,0) point - float[] origin = new float[] { 0.f, 0.f}; - mapPoints(origin); - - // translate the vector data as points - mapPoints(dst, dstIndex, src, srcIndex, ptCount); - - // then substract the transformed origin. - final int count = ptCount * 2; - for (int i = 0 ; i < count ; i += 2) { - dst[dstIndex + i] = dst[dstIndex + i] - origin[0]; - dst[dstIndex + i + 1] = dst[dstIndex + i + 1] - origin[1]; - } - } else { - // make a copy of the matrix - Matrix_Delegate copy = new Matrix_Delegate(mValues); - - // remove the translation - setTranslate(copy.mValues, 0, 0); - - // map the content as points. - copy.mapPoints(dst, dstIndex, src, srcIndex, ptCount); - } - } - - /** - * multiply two matrices and store them in a 3rd. - * <p/>This in effect does dest = a*b - * dest cannot be the same as a or b. - */ - /*package*/ static void multiply(float dest[], float[] a, float[] b) { - // first row - dest[0] = b[0] * a[0] + b[1] * a[3] + b[2] * a[6]; - dest[1] = b[0] * a[1] + b[1] * a[4] + b[2] * a[7]; - dest[2] = b[0] * a[2] + b[1] * a[5] + b[2] * a[8]; - - // 2nd row - dest[3] = b[3] * a[0] + b[4] * a[3] + b[5] * a[6]; - dest[4] = b[3] * a[1] + b[4] * a[4] + b[5] * a[7]; - dest[5] = b[3] * a[2] + b[4] * a[5] + b[5] * a[8]; - - // 3rd row - dest[6] = b[6] * a[0] + b[7] * a[3] + b[8] * a[6]; - dest[7] = b[6] * a[1] + b[7] * a[4] + b[8] * a[7]; - dest[8] = b[6] * a[2] + b[7] * a[5] + b[8] * a[8]; - } - - /** - * Returns a matrix that represents a given translate - * @param dx - * @param dy - * @return - */ - /*package*/ static float[] getTranslate(float dx, float dy) { - return setTranslate(new float[9], dx, dy); - } - - /*package*/ static float[] setTranslate(float[] dest, float dx, float dy) { - dest[0] = 1; - dest[1] = 0; - dest[2] = dx; - dest[3] = 0; - dest[4] = 1; - dest[5] = dy; - dest[6] = 0; - dest[7] = 0; - dest[8] = 1; - return dest; - } - - /*package*/ static float[] getScale(float sx, float sy) { - return new float[] { sx, 0, 0, 0, sy, 0, 0, 0, 1 }; - } - - /** - * Returns a matrix that represents the given scale info. - * @param sx - * @param sy - * @param px - * @param py - */ - /*package*/ static float[] getScale(float sx, float sy, float px, float py) { - float[] tmp = new float[9]; - float[] tmp2 = new float[9]; - - // TODO: do it in one pass - - // translate tmp so that the pivot is in 0,0 - setTranslate(tmp, -px, -py); - - // scale into tmp2 - multiply(tmp2, tmp, getScale(sx, sy)); - - // translate back the pivot back into tmp - multiply(tmp, tmp2, getTranslate(px, py)); - - return tmp; - } - - - /*package*/ static float[] getRotate(float degrees) { - double rad = Math.toRadians(degrees); - float sin = (float)Math.sin(rad); - float cos = (float)Math.cos(rad); - - return getRotate(sin, cos); - } - - /*package*/ static float[] getRotate(float sin, float cos) { - return setRotate(new float[9], sin, cos); - } - - /*package*/ static float[] setRotate(float[] dest, float degrees) { - double rad = Math.toRadians(degrees); - float sin = (float)Math.sin(rad); - float cos = (float)Math.cos(rad); - - return setRotate(dest, sin, cos); - } - - /*package*/ static float[] setRotate(float[] dest, float sin, float cos) { - dest[0] = cos; - dest[1] = -sin; - dest[2] = 0; - dest[3] = sin; - dest[4] = cos; - dest[5] = 0; - dest[6] = 0; - dest[7] = 0; - dest[8] = 1; - return dest; - } - - /*package*/ static float[] getRotate(float degrees, float px, float py) { - float[] tmp = new float[9]; - float[] tmp2 = new float[9]; - - // TODO: do it in one pass - - // translate so that the pivot is in 0,0 - setTranslate(tmp, -px, -py); - - // rotate into tmp2 - double rad = Math.toRadians(degrees); - float cos = (float)Math.cos(rad); - float sin = (float)Math.sin(rad); - multiply(tmp2, tmp, getRotate(sin, cos)); - - // translate back the pivot back into tmp - multiply(tmp, tmp2, getTranslate(px, py)); - - return tmp; - } - - /*package*/ static float[] getSkew(float kx, float ky) { - return new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 }; - } - - /*package*/ static float[] getSkew(float kx, float ky, float px, float py) { - float[] tmp = new float[9]; - float[] tmp2 = new float[9]; - - // TODO: do it in one pass - - // translate so that the pivot is in 0,0 - setTranslate(tmp, -px, -py); - - // skew into tmp2 - multiply(tmp2, tmp, new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 }); - // translate back the pivot back into tmp - multiply(tmp, tmp2, getTranslate(px, py)); - - return tmp; - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java deleted file mode 100644 index 1f0eb3bab55b..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.layoutlib.bridge.impl.GcSnapshot; -import com.android.ninepatch.NinePatchChunk; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.graphics.drawable.NinePatchDrawable; - -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.lang.ref.SoftReference; -import java.util.HashMap; -import java.util.Map; - -/** - * Delegate implementing the native methods of android.graphics.NinePatch - * - * Through the layoutlib_create tool, the original native methods of NinePatch have been replaced - * by calls to methods of the same name in this delegate class. - * - * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager} - * around to map int to instance of the delegate. - * - */ -public final class NinePatch_Delegate { - - // ---- delegate manager ---- - private static final DelegateManager<NinePatch_Delegate> sManager = - new DelegateManager<NinePatch_Delegate>(NinePatch_Delegate.class); - - // ---- delegate helper data ---- - /** - * Cache map for {@link NinePatchChunk}. - * When the chunks are created they are serialized into a byte[], and both are put - * in the cache, using a {@link SoftReference} for the chunk. The default Java classes - * for {@link NinePatch} and {@link NinePatchDrawable} only reference to the byte[] data, and - * provide this for drawing. - * Using the cache map allows us to not have to deserialize the byte[] back into a - * {@link NinePatchChunk} every time a rendering is done. - */ - private final static Map<byte[], SoftReference<NinePatchChunk>> sChunkCache = - new HashMap<byte[], SoftReference<NinePatchChunk>>(); - - // ---- delegate data ---- - private byte[] chunk; - - - // ---- Public Helper methods ---- - - /** - * Serializes the given chunk. - * - * @return the serialized data for the chunk. - */ - public static byte[] serialize(NinePatchChunk chunk) { - // serialize the chunk to get a byte[] - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = null; - try { - oos = new ObjectOutputStream(baos); - oos.writeObject(chunk); - } catch (IOException e) { - Bridge.getLog().error(null, "Failed to serialize NinePatchChunk.", e, null /*data*/); - return null; - } finally { - if (oos != null) { - try { - oos.close(); - } catch (IOException ignored) { - } - } - } - - // get the array and add it to the cache - byte[] array = baos.toByteArray(); - sChunkCache.put(array, new SoftReference<NinePatchChunk>(chunk)); - return array; - } - - /** - * Returns a {@link NinePatchChunk} object for the given serialized representation. - * - * If the chunk is present in the cache then the object from the cache is returned, otherwise - * the array is deserialized into a {@link NinePatchChunk} object. - * - * @param array the serialized representation of the chunk. - * @return the NinePatchChunk or null if deserialization failed. - */ - public static NinePatchChunk getChunk(byte[] array) { - SoftReference<NinePatchChunk> chunkRef = sChunkCache.get(array); - NinePatchChunk chunk = chunkRef.get(); - if (chunk == null) { - ByteArrayInputStream bais = new ByteArrayInputStream(array); - ObjectInputStream ois = null; - try { - ois = new ObjectInputStream(bais); - chunk = (NinePatchChunk) ois.readObject(); - - // put back the chunk in the cache - if (chunk != null) { - sChunkCache.put(array, new SoftReference<NinePatchChunk>(chunk)); - } - } catch (IOException e) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "Failed to deserialize NinePatchChunk content.", e, null /*data*/); - return null; - } catch (ClassNotFoundException e) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "Failed to deserialize NinePatchChunk class.", e, null /*data*/); - return null; - } finally { - if (ois != null) { - try { - ois.close(); - } catch (IOException ignored) { - } - } - } - } - - return chunk; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static boolean isNinePatchChunk(byte[] chunk) { - NinePatchChunk chunkObject = getChunk(chunk); - return chunkObject != null; - - } - - @LayoutlibDelegate - /*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. - NinePatch_Delegate newDelegate = new NinePatch_Delegate(); - newDelegate.chunk = chunk; - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static void nativeFinalize(long chunk) { - sManager.removeJavaReferenceFor(chunk); - } - - - @LayoutlibDelegate - /*package*/ static long nativeGetTransparentRegion(Bitmap bitmap, long chunk, Rect location) { - return 0; - } - - static byte[] getChunk(long nativeNinePatch) { - NinePatch_Delegate delegate = sManager.getDelegate(nativeNinePatch); - if (delegate != null) { - return delegate.chunk; - } - return null; - } - -} diff --git a/tools/layoutlib/bridge/src/android/graphics/PaintFlagsDrawFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PaintFlagsDrawFilter_Delegate.java deleted file mode 100644 index fa20746e4495..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/PaintFlagsDrawFilter_Delegate.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate implementing the native methods of android.graphics.PaintFlagsDrawFilter - * - * Through the layoutlib_create tool, the original native methods of PaintFlagsDrawFilter 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 PaintFlagsDrawFilter class. - * - * Because this extends {@link DrawFilter_Delegate}, there's no need to use a - * {@link DelegateManager}, as all the DrawFilter classes will be added to the manager owned by - * {@link DrawFilter_Delegate}. - * - * @see DrawFilter_Delegate - * - */ -public class PaintFlagsDrawFilter_Delegate extends DrawFilter_Delegate { - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - @Override - public boolean isSupported() { - return false; - } - - @Override - public String getSupportMessage() { - return "Paint Flags Draw Filters are not supported."; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static long nativeConstructor(int clearBits, int setBits) { - PaintFlagsDrawFilter_Delegate newDelegate = new PaintFlagsDrawFilter_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java deleted file mode 100644 index 60e5cd99854a..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java +++ /dev/null @@ -1,1329 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.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.annotation.Nullable; -import android.graphics.FontFamily_Delegate.FontVariant; -import android.graphics.Paint.FontMetrics; -import android.graphics.Paint.FontMetricsInt; -import android.text.TextUtils; - -import java.awt.BasicStroke; -import java.awt.Font; -import java.awt.Shape; -import java.awt.Stroke; -import java.awt.Toolkit; -import java.awt.geom.AffineTransform; -import java.util.ArrayList; -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 - * - * Through the layoutlib_create tool, the original native methods of Paint 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 Paint class. - * - * @see DelegateManager - * - */ -public class Paint_Delegate { - - /** - * Class associating a {@link Font} and its {@link java.awt.FontMetrics}. - */ - /*package*/ static final class FontInfo { - Font mFont; - java.awt.FontMetrics mMetrics; - } - - // ---- delegate manager ---- - private static final DelegateManager<Paint_Delegate> sManager = - new DelegateManager<Paint_Delegate>(Paint_Delegate.class); - private static long sFinalizer = -1; - - // ---- delegate helper data ---- - - // This list can contain null elements. - private List<FontInfo> mFonts; - - // ---- delegate data ---- - private int mFlags; - private int mColor; - private int mStyle; - private int mCap; - private int mJoin; - private int mTextAlign; - private Typeface_Delegate mTypeface; - private float mStrokeWidth; - private float mStrokeMiter; - private float mTextSize; - private float mTextScaleX; - private float mTextSkewX; - private int mHintingMode = Paint.HINTING_ON; - private int mHyphenEdit; - private float mLetterSpacing; // not used in actual text rendering. - private float mWordSpacing; // 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; - - private int mPorterDuffMode = Xfermode.DEFAULT; - private ColorFilter_Delegate mColorFilter; - private Shader_Delegate mShader; - private PathEffect_Delegate mPathEffect; - private MaskFilter_Delegate mMaskFilter; - - private Locale mLocale = Locale.getDefault(); - - // Used only to assert invariants. - public long mNativeTypeface; - - // ---- Public Helper methods ---- - - @Nullable - public static Paint_Delegate getDelegate(long native_paint) { - return sManager.getDelegate(native_paint); - } - - /** - * Returns the list of {@link Font} objects. - */ - public List<FontInfo> getFonts() { - return mFonts; - } - - public boolean isAntiAliased() { - return (mFlags & Paint.ANTI_ALIAS_FLAG) != 0; - } - - public boolean isFilterBitmap() { - return (mFlags & Paint.FILTER_BITMAP_FLAG) != 0; - } - - public int getStyle() { - return mStyle; - } - - public int getColor() { - return mColor; - } - - public int getAlpha() { - return mColor >>> 24; - } - - public void setAlpha(int alpha) { - mColor = (alpha << 24) | (mColor & 0x00FFFFFF); - } - - public int getTextAlign() { - return mTextAlign; - } - - public float getStrokeWidth() { - return mStrokeWidth; - } - - /** - * returns the value of stroke miter needed by the java api. - */ - public float getJavaStrokeMiter() { - return mStrokeMiter; - } - - public int getJavaCap() { - switch (Paint.sCapArray[mCap]) { - case BUTT: - return BasicStroke.CAP_BUTT; - case ROUND: - return BasicStroke.CAP_ROUND; - default: - case SQUARE: - return BasicStroke.CAP_SQUARE; - } - } - - public int getJavaJoin() { - switch (Paint.sJoinArray[mJoin]) { - default: - case MITER: - return BasicStroke.JOIN_MITER; - case ROUND: - return BasicStroke.JOIN_ROUND; - case BEVEL: - return BasicStroke.JOIN_BEVEL; - } - } - - public Stroke getJavaStroke() { - if (mPathEffect != null) { - if (mPathEffect.isSupported()) { - Stroke stroke = mPathEffect.getStroke(this); - assert stroke != null; - if (stroke != null) { - return stroke; - } - } else { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_PATHEFFECT, - mPathEffect.getSupportMessage(), - null, null /*data*/); - } - } - - // if no custom stroke as been set, set the default one. - return new BasicStroke( - getStrokeWidth(), - getJavaCap(), - getJavaJoin(), - getJavaStrokeMiter()); - } - - /** - * Returns the {@link PorterDuff.Mode} as an int - */ - public int getPorterDuffMode() { - return mPorterDuffMode; - } - - /** - * Returns the {@link ColorFilter} delegate or null if none have been set - * - * @return the delegate or null. - */ - public ColorFilter_Delegate getColorFilter() { - return mColorFilter; - } - - public void setColorFilter(long colorFilterPtr) { - mColorFilter = ColorFilter_Delegate.getDelegate(colorFilterPtr); - } - - public void setShader(long shaderPtr) { - mShader = Shader_Delegate.getDelegate(shaderPtr); - } - - /** - * Returns the {@link Shader} delegate or null if none have been set - * - * @return the delegate or null. - */ - public Shader_Delegate getShader() { - return mShader; - } - - /** - * Returns the {@link MaskFilter} delegate or null if none have been set - * - * @return the delegate or null. - */ - public MaskFilter_Delegate getMaskFilter() { - return mMaskFilter; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static int nGetFlags(long nativePaint) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return 0; - } - - return delegate.mFlags; - } - - - - @LayoutlibDelegate - /*package*/ static void nSetFlags(long nativePaint, int flags) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return; - } - - delegate.mFlags = flags; - } - - @LayoutlibDelegate - /*package*/ static void nSetFilterBitmap(long nativePaint, boolean filter) { - setFlag(nativePaint, Paint.FILTER_BITMAP_FLAG, filter); - } - - @LayoutlibDelegate - /*package*/ static int nGetHinting(long nativePaint) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return Paint.HINTING_ON; - } - - return delegate.mHintingMode; - } - - @LayoutlibDelegate - /*package*/ static void nSetHinting(long nativePaint, int mode) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return; - } - - delegate.mHintingMode = mode; - } - - @LayoutlibDelegate - /*package*/ static void nSetAntiAlias(long nativePaint, boolean aa) { - setFlag(nativePaint, Paint.ANTI_ALIAS_FLAG, aa); - } - - @LayoutlibDelegate - /*package*/ static void nSetSubpixelText(long nativePaint, - boolean subpixelText) { - setFlag(nativePaint, Paint.SUBPIXEL_TEXT_FLAG, subpixelText); - } - - @LayoutlibDelegate - /*package*/ static void nSetUnderlineText(long nativePaint, - boolean underlineText) { - setFlag(nativePaint, Paint.UNDERLINE_TEXT_FLAG, underlineText); - } - - @LayoutlibDelegate - /*package*/ static void nSetStrikeThruText(long nativePaint, - boolean strikeThruText) { - setFlag(nativePaint, Paint.STRIKE_THRU_TEXT_FLAG, strikeThruText); - } - - @LayoutlibDelegate - /*package*/ static void nSetFakeBoldText(long nativePaint, - boolean fakeBoldText) { - setFlag(nativePaint, Paint.FAKE_BOLD_TEXT_FLAG, fakeBoldText); - } - - @LayoutlibDelegate - /*package*/ static void nSetDither(long nativePaint, boolean dither) { - setFlag(nativePaint, Paint.DITHER_FLAG, dither); - } - - @LayoutlibDelegate - /*package*/ static void nSetLinearText(long nativePaint, boolean linearText) { - setFlag(nativePaint, Paint.LINEAR_TEXT_FLAG, linearText); - } - - @LayoutlibDelegate - /*package*/ static int nGetColor(long nativePaint) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return 0; - } - - return delegate.mColor; - } - - @LayoutlibDelegate - /*package*/ static void nSetColor(long nativePaint, int color) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return; - } - - delegate.mColor = color; - } - - @LayoutlibDelegate - /*package*/ static int nGetAlpha(long nativePaint) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return 0; - } - - return delegate.getAlpha(); - } - - @LayoutlibDelegate - /*package*/ static void nSetAlpha(long nativePaint, int a) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return; - } - - delegate.setAlpha(a); - } - - @LayoutlibDelegate - /*package*/ static float nGetStrokeWidth(long nativePaint) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return 1.f; - } - - return delegate.mStrokeWidth; - } - - @LayoutlibDelegate - /*package*/ static void nSetStrokeWidth(long nativePaint, float width) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return; - } - - delegate.mStrokeWidth = width; - } - - @LayoutlibDelegate - /*package*/ static float nGetStrokeMiter(long nativePaint) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return 1.f; - } - - return delegate.mStrokeMiter; - } - - @LayoutlibDelegate - /*package*/ static void nSetStrokeMiter(long nativePaint, float miter) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return; - } - - delegate.mStrokeMiter = miter; - } - - @LayoutlibDelegate - /*package*/ static void nSetShadowLayer(long paint, float radius, float dx, float dy, - int color) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Paint.setShadowLayer is not supported.", null, null /*data*/); - } - - @LayoutlibDelegate - /*package*/ static boolean nHasShadowLayer(long paint) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Paint.hasShadowLayer is not supported.", null, null /*data*/); - return false; - } - - @LayoutlibDelegate - /*package*/ static boolean nIsElegantTextHeight(long nativePaint) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - return delegate != null && delegate.mFontVariant == FontVariant.ELEGANT; - } - - @LayoutlibDelegate - /*package*/ static void nSetElegantTextHeight(long nativePaint, - boolean elegant) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return; - } - - delegate.mFontVariant = elegant ? FontVariant.ELEGANT : FontVariant.COMPACT; - } - - @LayoutlibDelegate - /*package*/ static float nGetTextSize(long nativePaint) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return 1.f; - } - - return delegate.mTextSize; - } - - @LayoutlibDelegate - /*package*/ static void nSetTextSize(long nativePaint, float textSize) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return; - } - - if (delegate.mTextSize != textSize) { - delegate.mTextSize = textSize; - delegate.updateFontObject(); - } - } - - @LayoutlibDelegate - /*package*/ static float nGetTextScaleX(long nativePaint) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return 1.f; - } - - return delegate.mTextScaleX; - } - - @LayoutlibDelegate - /*package*/ static void nSetTextScaleX(long nativePaint, float scaleX) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return; - } - - if (delegate.mTextScaleX != scaleX) { - delegate.mTextScaleX = scaleX; - delegate.updateFontObject(); - } - } - - @LayoutlibDelegate - /*package*/ static float nGetTextSkewX(long nativePaint) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return 1.f; - } - - return delegate.mTextSkewX; - } - - @LayoutlibDelegate - /*package*/ static void nSetTextSkewX(long nativePaint, float skewX) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return; - } - - if (delegate.mTextSkewX != skewX) { - delegate.mTextSkewX = skewX; - delegate.updateFontObject(); - } - } - - @LayoutlibDelegate - /*package*/ static float nAscent(long nativePaint, long nativeTypeface) { - // get the delegate - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return 0; - } - - if (delegate.mFonts.size() > 0) { - java.awt.FontMetrics javaMetrics = delegate.mFonts.get(0).mMetrics; - // Android expects negative ascent so we invert the value from Java. - return - javaMetrics.getAscent(); - } - - return 0; - } - - @LayoutlibDelegate - /*package*/ static float nDescent(long nativePaint, long nativeTypeface) { - // get the delegate - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return 0; - } - - if (delegate.mFonts.size() > 0) { - java.awt.FontMetrics javaMetrics = delegate.mFonts.get(0).mMetrics; - return javaMetrics.getDescent(); - } - - return 0; - - } - - @LayoutlibDelegate - /*package*/ static float nGetFontMetrics(long nativePaint, long nativeTypeface, - FontMetrics metrics) { - // get the delegate - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return 0; - } - - return delegate.getFontMetrics(metrics); - } - - @LayoutlibDelegate - /*package*/ static int nGetFontMetricsInt(long nativePaint, - long nativeTypeface, FontMetricsInt fmi) { - // get the delegate - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return 0; - } - - if (delegate.mFonts.size() > 0) { - java.awt.FontMetrics javaMetrics = delegate.mFonts.get(0).mMetrics; - if (fmi != null) { - // Android expects negative ascent so we invert the value from Java. - fmi.top = (int)(- javaMetrics.getMaxAscent() * 1.15); - fmi.ascent = - javaMetrics.getAscent(); - fmi.descent = javaMetrics.getDescent(); - fmi.bottom = (int)(javaMetrics.getMaxDescent() * 1.15); - fmi.leading = javaMetrics.getLeading(); - } - - return javaMetrics.getHeight(); - } - - return 0; - } - - @LayoutlibDelegate - /*package*/ static int nBreakText(long nativePaint, long nativeTypeface, char[] text, - int index, int count, float maxWidth, int bidiFlags, float[] measuredWidth) { - - // get the delegate - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return 0; - } - - int inc = count > 0 ? 1 : -1; - - int measureIndex = 0; - for (int i = index; i != index + count; i += inc, measureIndex++) { - int start, end; - if (i < index) { - start = i; - end = index; - } else { - start = index; - end = i; - } - - // measure from start to end - RectF bounds = delegate.measureText(text, start, end - start + 1, null, 0, bidiFlags); - float res = bounds.right - bounds.left; - - if (measuredWidth != null) { - measuredWidth[measureIndex] = res; - } - - if (res > maxWidth) { - // we should not return this char index, but since it's 0-based - // and we need to return a count, we simply return measureIndex; - return measureIndex; - } - - } - - return measureIndex; - } - - @LayoutlibDelegate - /*package*/ static int nBreakText(long nativePaint, long nativeTypeface, String text, - boolean measureForwards, - float maxWidth, int bidiFlags, float[] measuredWidth) { - return nBreakText(nativePaint, nativeTypeface, text.toCharArray(), 0, text.length(), - maxWidth, bidiFlags, measuredWidth); - } - - @LayoutlibDelegate - /*package*/ static long nInit() { - Paint_Delegate newDelegate = new Paint_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static long nInitWithPaint(long paint) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(paint); - if (delegate == null) { - return 0; - } - - Paint_Delegate newDelegate = new Paint_Delegate(delegate); - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static void nReset(long native_object) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return; - } - - delegate.reset(); - } - - @LayoutlibDelegate - /*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) { - return; - } - - // get the delegate from the native int. - Paint_Delegate delegate_src = sManager.getDelegate(native_src); - if (delegate_src == null) { - return; - } - - delegate_dst.set(delegate_src); - } - - @LayoutlibDelegate - /*package*/ static int nGetStyle(long native_object) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return 0; - } - - return delegate.mStyle; - } - - @LayoutlibDelegate - /*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) { - return; - } - - delegate.mStyle = style; - } - - @LayoutlibDelegate - /*package*/ static int nGetStrokeCap(long native_object) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return 0; - } - - return delegate.mCap; - } - - @LayoutlibDelegate - /*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) { - return; - } - - delegate.mCap = cap; - } - - @LayoutlibDelegate - /*package*/ static int nGetStrokeJoin(long native_object) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return 0; - } - - return delegate.mJoin; - } - - @LayoutlibDelegate - /*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) { - return; - } - - delegate.mJoin = join; - } - - @LayoutlibDelegate - /*package*/ static boolean nGetFillPath(long native_object, long src, long dst) { - Paint_Delegate paint = sManager.getDelegate(native_object); - if (paint == null) { - return false; - } - - Path_Delegate srcPath = Path_Delegate.getDelegate(src); - if (srcPath == null) { - return true; - } - - Path_Delegate dstPath = Path_Delegate.getDelegate(dst); - if (dstPath == null) { - return true; - } - - Stroke stroke = paint.getJavaStroke(); - Shape strokeShape = stroke.createStrokedShape(srcPath.getJavaShape()); - - dstPath.setJavaShape(strokeShape); - - // FIXME figure out the return value? - return true; - } - - @LayoutlibDelegate - /*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) { - return shader; - } - - delegate.mShader = Shader_Delegate.getDelegate(shader); - - return shader; - } - - @LayoutlibDelegate - /*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) { - return filter; - } - - delegate.mColorFilter = ColorFilter_Delegate.getDelegate(filter); - - // Log warning if it's not supported. - if (delegate.mColorFilter != null && !delegate.mColorFilter.isSupported()) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_COLORFILTER, - delegate.mColorFilter.getSupportMessage(), null, null /*data*/); - } - - return filter; - } - - @LayoutlibDelegate - /*package*/ static void nSetXfermode(long native_object, int xfermode) { - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return; - } - delegate.mPorterDuffMode = xfermode; - } - - @LayoutlibDelegate - /*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) { - return effect; - } - - delegate.mPathEffect = PathEffect_Delegate.getDelegate(effect); - - return effect; - } - - @LayoutlibDelegate - /*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) { - return maskfilter; - } - - delegate.mMaskFilter = MaskFilter_Delegate.getDelegate(maskfilter); - - // since none of those are supported, display a fidelity warning right away - if (delegate.mMaskFilter != null && !delegate.mMaskFilter.isSupported()) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_MASKFILTER, - delegate.mMaskFilter.getSupportMessage(), null, null /*data*/); - } - - return maskfilter; - } - - @LayoutlibDelegate - /*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) { - return 0; - } - - Typeface_Delegate typefaceDelegate = Typeface_Delegate.getDelegate(typeface); - if (delegate.mTypeface != typefaceDelegate || delegate.mNativeTypeface != typeface) { - delegate.mTypeface = Typeface_Delegate.getDelegate(typeface); - delegate.mNativeTypeface = typeface; - delegate.updateFontObject(); - } - return typeface; - } - - @LayoutlibDelegate - /*package*/ static int nGetTextAlign(long native_object) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return 0; - } - - return delegate.mTextAlign; - } - - @LayoutlibDelegate - /*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) { - return; - } - - delegate.mTextAlign = align; - } - - @LayoutlibDelegate - /*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; - } - - delegate.setTextLocale(locale); - return 0; - } - - @LayoutlibDelegate - /*package*/ static void nSetTextLocalesByMinikinLangListId(long paintPtr, - int mMinikinLangListId) { - // FIXME - } - - @LayoutlibDelegate - /*package*/ static float nGetTextAdvances(long native_object, long native_typeface, - char[] text, int index, int count, int contextIndex, int contextCount, - int bidiFlags, float[] advances, int advancesIndex) { - - if (advances != null) - for (int i = advancesIndex; i< advancesIndex+count; i++) - advances[i]=0; - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return 0.f; - } - - // 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, advances, advancesIndex, bidiFlags); - return bounds.right - bounds.left; - } - - @LayoutlibDelegate - /*package*/ static float nGetTextAdvances(long native_object, long native_typeface, - String text, int start, int end, int contextStart, int contextEnd, - 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 nGetTextAdvances(native_object, native_typeface, buffer, 0, count, - contextStart, contextEnd - contextStart, bidiFlags, advances, advancesIndex); - } - - @LayoutlibDelegate - /*package*/ static int nGetTextRunCursor(Paint paint, long native_object, long typefacePtr, - char[] text, int contextStart, int contextLength, int flags, int offset, - int cursorOpt) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Paint.getTextRunCursor is not supported.", null, null /*data*/); - return 0; - } - - @LayoutlibDelegate - /*package*/ static int nGetTextRunCursor(Paint paint, long native_object, long typefacePtr, - String text, int contextStart, int contextEnd, int flags, int offset, int cursorOpt) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Paint.getTextRunCursor is not supported.", null, null /*data*/); - return 0; - } - - @LayoutlibDelegate - /*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, - "Paint.getTextPath is not supported.", null, null /*data*/); - } - - @LayoutlibDelegate - /*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, - "Paint.getTextPath is not supported.", null, null /*data*/); - } - - @LayoutlibDelegate - /*package*/ static void nGetStringBounds(long nativePaint, long native_typeface, - String text, int start, int end, int bidiFlags, Rect bounds) { - nGetCharArrayBounds(nativePaint, native_typeface, text.toCharArray(), start, - end - start, bidiFlags, bounds); - } - - @LayoutlibDelegate - /*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. - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return; - } - - // assert that the typeface passed is actually the one that we had stored. - assert (native_typeface == delegate.mNativeTypeface); - - delegate.measureText(text, index, count, null, 0, bidiFlags).roundOut(bounds); - } - - @LayoutlibDelegate - /*package*/ static long nGetNativeFinalizer() { - synchronized (Paint_Delegate.class) { - if (sFinalizer == -1) { - sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer( - sManager::removeJavaReferenceFor); - } - } - return sFinalizer; - } - - @LayoutlibDelegate - /*package*/ static float nGetLetterSpacing(long nativePaint) { - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return 0; - } - return delegate.mLetterSpacing; - } - - @LayoutlibDelegate - /*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); - if (delegate == null) { - return; - } - delegate.mLetterSpacing = letterSpacing; - } - - @LayoutlibDelegate - /*package*/ static float nGetWordSpacing(long nativePaint) { - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return 0; - } - return delegate.mWordSpacing; - } - - @LayoutlibDelegate - /*package*/ static void nSetWordSpacing(long nativePaint, float wordSpacing) { - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return; - } - delegate.mWordSpacing = wordSpacing; - } - - @LayoutlibDelegate - /*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 nGetHyphenEdit(long nativePaint) { - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return 0; - } - return delegate.mHyphenEdit; - } - - @LayoutlibDelegate - /*package*/ static void nSetHyphenEdit(long nativePaint, int hyphen) { - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return; - } - delegate.mHyphenEdit = hyphen; - } - - @LayoutlibDelegate - /*package*/ static boolean nHasGlyph(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 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]; - 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++) { - sum += advances[i]; - } - return sum; - } - - @LayoutlibDelegate - /*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]; - 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++) { - sum += advances[i]; - } - float distanceToI = sum - advance; - float distanceToIMinus1 = advance - (sum - advances[i]); - return distanceToI > distanceToIMinus1 ? i : i - 1; - } - - // ---- Private delegate/helper methods ---- - - /*package*/ Paint_Delegate() { - reset(); - } - - private Paint_Delegate(Paint_Delegate paint) { - set(paint); - } - - private void set(Paint_Delegate paint) { - mFlags = paint.mFlags; - mColor = paint.mColor; - mStyle = paint.mStyle; - mCap = paint.mCap; - mJoin = paint.mJoin; - mTextAlign = paint.mTextAlign; - - boolean needsFontUpdate = false; - if (mTypeface != paint.mTypeface || mNativeTypeface != paint.mNativeTypeface) { - mTypeface = paint.mTypeface; - mNativeTypeface = paint.mNativeTypeface; - needsFontUpdate = true; - } - - if (mTextSize != paint.mTextSize) { - mTextSize = paint.mTextSize; - needsFontUpdate = true; - } - - if (mTextScaleX != paint.mTextScaleX) { - mTextScaleX = paint.mTextScaleX; - needsFontUpdate = true; - } - - if (mTextSkewX != paint.mTextSkewX) { - mTextSkewX = paint.mTextSkewX; - needsFontUpdate = true; - } - - mStrokeWidth = paint.mStrokeWidth; - mStrokeMiter = paint.mStrokeMiter; - mPorterDuffMode = paint.mPorterDuffMode; - mColorFilter = paint.mColorFilter; - mShader = paint.mShader; - mPathEffect = paint.mPathEffect; - mMaskFilter = paint.mMaskFilter; - mHintingMode = paint.mHintingMode; - - if (needsFontUpdate) { - updateFontObject(); - } - } - - private void reset() { - mFlags = Paint.HIDDEN_DEFAULT_PAINT_FLAGS; - mColor = 0xFF000000; - mStyle = Paint.Style.FILL.nativeInt; - mCap = Paint.Cap.BUTT.nativeInt; - mJoin = Paint.Join.MITER.nativeInt; - mTextAlign = 0; - mTypeface = Typeface_Delegate.getDelegate(Typeface.sDefaults[0].native_instance); - mNativeTypeface = 0; - mStrokeWidth = 1.f; - mStrokeMiter = 4.f; - mTextSize = 20.f; - mTextScaleX = 1.f; - mTextSkewX = 0.f; - mPorterDuffMode = Xfermode.DEFAULT; - mColorFilter = null; - mShader = null; - mPathEffect = null; - mMaskFilter = null; - updateFontObject(); - mHintingMode = Paint.HINTING_ON; - } - - /** - * Update the {@link Font} object from the typeface, text size and scaling - */ - @SuppressWarnings("deprecation") - private void updateFontObject() { - if (mTypeface != null) { - // Get the fonts from the TypeFace object. - List<Font> fonts = mTypeface.getFonts(mFontVariant); - - if (fonts.isEmpty()) { - mFonts = Collections.emptyList(); - return; - } - - // create new font objects as well as FontMetrics, based on the current text size - // and skew info. - int nFonts = fonts.size(); - ArrayList<FontInfo> infoList = new ArrayList<FontInfo>(nFonts); - //noinspection ForLoopReplaceableByForEach (avoid iterator instantiation) - for (int i = 0; i < nFonts; i++) { - Font font = fonts.get(i); - if (font == null) { - // If the font is null, add null to infoList. When rendering the text, if this - // null is reached, a warning will be logged. - infoList.add(null); - continue; - } - FontInfo info = new FontInfo(); - info.mFont = font.deriveFont(mTextSize); - if (mTextScaleX != 1.0 || mTextSkewX != 0) { - // TODO: support skew - info.mFont = info.mFont.deriveFont(new AffineTransform( - mTextScaleX, mTextSkewX, 0, 1, 0, 0)); - } - // The metrics here don't have anti-aliasing set. - info.mMetrics = Toolkit.getDefaultToolkit().getFontMetrics(info.mFont); - - infoList.add(info); - } - - mFonts = Collections.unmodifiableList(infoList); - } - } - - /*package*/ RectF measureText(char[] text, int index, int count, float[] advances, - int advancesIndex, int bidiFlags) { - return new BidiRenderer(null, this, text) - .renderText(index, index + count, bidiFlags, advances, advancesIndex, false); - } - - /*package*/ RectF measureText(char[] text, int index, int count, float[] advances, - int advancesIndex, boolean isRtl) { - return new BidiRenderer(null, this, text) - .renderText(index, index + count, isRtl, advances, advancesIndex, false); - } - - private float getFontMetrics(FontMetrics metrics) { - if (mFonts.size() > 0) { - java.awt.FontMetrics javaMetrics = mFonts.get(0).mMetrics; - if (metrics != null) { - // Android expects negative ascent so we invert the value from Java. - metrics.top = - javaMetrics.getMaxAscent(); - metrics.ascent = - javaMetrics.getAscent(); - metrics.descent = javaMetrics.getDescent(); - metrics.bottom = javaMetrics.getMaxDescent(); - metrics.leading = javaMetrics.getLeading(); - } - - return javaMetrics.getHeight(); - } - - return 0; - } - - private void setTextLocale(String locale) { - mLocale = new Locale(locale); - } - - private static void setFlag(long nativePaint, int flagMask, boolean flagValue) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return; - } - - if (flagValue) { - delegate.mFlags |= flagMask; - } else { - delegate.mFlags &= ~flagMask; - } - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/PathDashPathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PathDashPathEffect_Delegate.java deleted file mode 100644 index fd9ba62e2695..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/PathDashPathEffect_Delegate.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import java.awt.Stroke; - -/** - * Delegate implementing the native methods of android.graphics.PathDashPathEffect - * - * Through the layoutlib_create tool, the original native methods of PathDashPathEffect 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 PathDashPathEffect class. - * - * Because this extends {@link PathEffect_Delegate}, there's no need to use a {@link DelegateManager}, - * as all the Shader classes will be added to the manager owned by {@link PathEffect_Delegate}. - * - * @see PathEffect_Delegate - * - */ -public class PathDashPathEffect_Delegate extends PathEffect_Delegate { - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - @Override - public Stroke getStroke(Paint_Delegate paint) { - // FIXME - return null; - } - - @Override - public boolean isSupported() { - return false; - } - - @Override - public String getSupportMessage() { - return "Path Dash Path Effects are not supported in Layout Preview mode."; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static long nativeCreate(long native_path, float advance, float phase, - int native_style) { - PathDashPathEffect_Delegate newDelegate = new PathDashPathEffect_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java deleted file mode 100644 index 000481ec7cc9..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import java.awt.Stroke; - -/** - * Delegate implementing the native methods of android.graphics.PathEffect - * - * Through the layoutlib_create tool, the original native methods of PathEffect 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 PathEffect class. - * - * This also serve as a base class for all PathEffect delegate classes. - * - * @see DelegateManager - * - */ -public abstract class PathEffect_Delegate { - - // ---- delegate manager ---- - protected static final DelegateManager<PathEffect_Delegate> sManager = - new DelegateManager<PathEffect_Delegate>(PathEffect_Delegate.class); - - // ---- delegate helper data ---- - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - public static PathEffect_Delegate getDelegate(long nativeShader) { - return sManager.getDelegate(nativeShader); - } - - public abstract Stroke getStroke(Paint_Delegate paint); - public abstract boolean isSupported(); - public abstract String getSupportMessage(); - - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static void nativeDestructor(long native_patheffect) { - sManager.removeJavaReferenceFor(native_patheffect); - } - - // ---- Private delegate/helper methods ---- - -} diff --git a/tools/layoutlib/bridge/src/android/graphics/PathMeasure_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PathMeasure_Delegate.java deleted file mode 100644 index 7f707c9aa01a..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/PathMeasure_Delegate.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * 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.graphics; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.layoutlib.bridge.util.CachedPathIteratorFactory; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import com.android.layoutlib.bridge.util.CachedPathIteratorFactory.CachedPathIterator; - -import java.awt.geom.PathIterator; - -/** - * Delegate implementing the native methods of {@link android.graphics.PathMeasure} - * <p/> - * Through the layoutlib_create tool, the original native methods of PathMeasure have been - * replaced by - * calls to methods of the same name in this delegate class. - * <p/> - * 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 PathMeasure class. - * - * @see DelegateManager - */ -public final class PathMeasure_Delegate { - - // ---- delegate manager ---- - private static final DelegateManager<PathMeasure_Delegate> sManager = - new DelegateManager<PathMeasure_Delegate>(PathMeasure_Delegate.class); - - // ---- delegate data ---- - private CachedPathIteratorFactory mOriginalPathIterator; - - private long mNativePath; - - - private PathMeasure_Delegate(long native_path, boolean forceClosed) { - mNativePath = native_path; - if (native_path != 0) { - if (forceClosed) { - // Copy the path and call close - native_path = Path_Delegate.nInit(native_path); - Path_Delegate.nClose(native_path); - } - - Path_Delegate pathDelegate = Path_Delegate.getDelegate(native_path); - mOriginalPathIterator = new CachedPathIteratorFactory(pathDelegate.getJavaShape() - .getPathIterator(null)); - } - } - - @LayoutlibDelegate - /*package*/ static long native_create(long native_path, boolean forceClosed) { - return sManager.addNewDelegate(new PathMeasure_Delegate(native_path, forceClosed)); - } - - @LayoutlibDelegate - /*package*/ static void native_destroy(long native_instance) { - sManager.removeJavaReferenceFor(native_instance); - } - - @LayoutlibDelegate - /*package*/ static boolean native_getPosTan(long native_instance, float distance, float pos[], - float tan[]) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "PathMeasure.getPostTan is not supported.", null, null); - return false; - } - - @LayoutlibDelegate - /*package*/ static boolean native_getMatrix(long native_instance, float distance, long - native_matrix, int flags) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "PathMeasure.getMatrix is not supported.", null, null); - return false; - } - - @LayoutlibDelegate - /*package*/ static boolean native_nextContour(long native_instance) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "PathMeasure.nextContour is not supported.", null, null); - return false; - } - - @LayoutlibDelegate - /*package*/ static void native_setPath(long native_instance, long native_path, boolean - forceClosed) { - PathMeasure_Delegate pathMeasure = sManager.getDelegate(native_instance); - assert pathMeasure != null; - - if (native_path != 0) { - if (forceClosed) { - // Copy the path and call close - native_path = Path_Delegate.nInit(native_path); - Path_Delegate.nClose(native_path); - } - - Path_Delegate pathDelegate = Path_Delegate.getDelegate(native_path); - pathMeasure.mOriginalPathIterator = new CachedPathIteratorFactory(pathDelegate.getJavaShape() - .getPathIterator(null)); - } - - pathMeasure.mNativePath = native_path; - } - - @LayoutlibDelegate - /*package*/ static float native_getLength(long native_instance) { - PathMeasure_Delegate pathMeasure = sManager.getDelegate(native_instance); - assert pathMeasure != null; - - if (pathMeasure.mOriginalPathIterator == null) { - return 0; - } - - return pathMeasure.mOriginalPathIterator.iterator().getTotalLength(); - } - - @LayoutlibDelegate - /*package*/ static boolean native_isClosed(long native_instance) { - PathMeasure_Delegate pathMeasure = sManager.getDelegate(native_instance); - assert pathMeasure != null; - - Path_Delegate path = Path_Delegate.getDelegate(pathMeasure.mNativePath); - if (path == null) { - return false; - } - - int type = 0; - float segment[] = new float[6]; - for (PathIterator pi = path.getJavaShape().getPathIterator(null); !pi.isDone(); pi.next()) { - type = pi.currentSegment(segment); - } - - // A path is a closed path if the last element is SEG_CLOSE - return type == PathIterator.SEG_CLOSE; - } - - @LayoutlibDelegate - /*package*/ static boolean native_getSegment(long native_instance, float startD, float stopD, - long native_dst_path, boolean startWithMoveTo) { - if (startD < 0) { - startD = 0; - } - - if (startD >= stopD) { - return false; - } - - PathMeasure_Delegate pathMeasure = sManager.getDelegate(native_instance); - assert pathMeasure != null; - - CachedPathIterator iterator = pathMeasure.mOriginalPathIterator.iterator(); - float accLength = startD; - boolean isZeroLength = true; // Whether the output has zero length or not - float[] points = new float[6]; - - iterator.jumpToSegment(accLength); - while (!iterator.isDone() && (stopD - accLength > 0.1f)) { - int type = iterator.currentSegment(points, stopD - accLength); - - if (accLength - iterator.getCurrentSegmentLength() <= stopD) { - if (startWithMoveTo) { - startWithMoveTo = false; - - // If this segment is a MOVETO, then we just use that one. If not, then we issue - // a first moveto - if (type != PathIterator.SEG_MOVETO) { - float[] lastPoint = new float[2]; - iterator.getCurrentSegmentEnd(lastPoint); - Path_Delegate.nMoveTo(native_dst_path, lastPoint[0], lastPoint[1]); - } - } - - isZeroLength = isZeroLength && iterator.getCurrentSegmentLength() > 0; - switch (type) { - case PathIterator.SEG_MOVETO: - Path_Delegate.nMoveTo(native_dst_path, points[0], points[1]); - break; - case PathIterator.SEG_LINETO: - Path_Delegate.nLineTo(native_dst_path, points[0], points[1]); - break; - case PathIterator.SEG_CLOSE: - Path_Delegate.nClose(native_dst_path); - break; - case PathIterator.SEG_CUBICTO: - Path_Delegate.nCubicTo(native_dst_path, points[0], points[1], - points[2], points[3], - points[4], points[5]); - break; - case PathIterator.SEG_QUADTO: - Path_Delegate.nQuadTo(native_dst_path, points[0], points[1], - points[2], - points[3]); - break; - default: - assert false; - } - } - - accLength += iterator.getCurrentSegmentLength(); - iterator.next(); - } - - return !isZeroLength; - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java deleted file mode 100644 index 50b916532319..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java +++ /dev/null @@ -1,896 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.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.Direction; -import android.graphics.Path.FillType; - -import java.awt.Shape; -import java.awt.geom.AffineTransform; -import java.awt.geom.Arc2D; -import java.awt.geom.Area; -import java.awt.geom.Ellipse2D; -import java.awt.geom.GeneralPath; -import java.awt.geom.Path2D; -import java.awt.geom.PathIterator; -import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; -import java.awt.geom.RoundRectangle2D; -import java.util.ArrayList; - -/** - * Delegate implementing the native methods of android.graphics.Path - * - * Through the layoutlib_create tool, the original native methods of Path 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 Path class. - * - * @see DelegateManager - * - */ -public final class Path_Delegate { - - // ---- delegate manager ---- - private static final DelegateManager<Path_Delegate> sManager = - new DelegateManager<Path_Delegate>(Path_Delegate.class); - - private static final float EPSILON = 1e-4f; - - // ---- delegate data ---- - private FillType mFillType = FillType.WINDING; - private Path2D mPath = new Path2D.Double(); - - private float mLastX = 0; - private float mLastY = 0; - - // true if the path contains does not contain a curve or line. - private boolean mCachedIsEmpty = true; - - // ---- Public Helper methods ---- - - public static Path_Delegate getDelegate(long nPath) { - return sManager.getDelegate(nPath); - } - - public Path2D getJavaShape() { - return mPath; - } - - public void setJavaShape(Shape shape) { - reset(); - mPath.append(shape, false /*connect*/); - } - - public void reset() { - mPath.reset(); - mLastX = 0; - mLastY = 0; - } - - public void setPathIterator(PathIterator iterator) { - reset(); - mPath.append(iterator, false /*connect*/); - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static long nInit() { - // create the delegate - Path_Delegate newDelegate = new Path_Delegate(); - - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static long nInit(long nPath) { - // create the delegate - Path_Delegate newDelegate = new Path_Delegate(); - - // get the delegate to copy, which could be null if nPath is 0 - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate != null) { - newDelegate.set(pathDelegate); - } - - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static void nReset(long nPath) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.reset(); - } - - @LayoutlibDelegate - /*package*/ static void nRewind(long nPath) { - // call out to reset since there's nothing to optimize in - // terms of data structs. - nReset(nPath); - } - - @LayoutlibDelegate - /*package*/ static void nSet(long native_dst, long nSrc) { - Path_Delegate pathDstDelegate = sManager.getDelegate(native_dst); - if (pathDstDelegate == null) { - return; - } - - Path_Delegate pathSrcDelegate = sManager.getDelegate(nSrc); - if (pathSrcDelegate == null) { - return; - } - - pathDstDelegate.set(pathSrcDelegate); - } - - @LayoutlibDelegate - /*package*/ static boolean nIsConvex(long nPath) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Path.isConvex is not supported.", null, null); - return true; - } - - @LayoutlibDelegate - /*package*/ static int nGetFillType(long nPath) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return 0; - } - - return pathDelegate.mFillType.nativeInt; - } - - @LayoutlibDelegate - public static void nSetFillType(long nPath, int ft) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.setFillType(Path.sFillTypeArray[ft]); - } - - @LayoutlibDelegate - /*package*/ static boolean nIsEmpty(long nPath) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - return pathDelegate == null || pathDelegate.isEmpty(); - - } - - @LayoutlibDelegate - /*package*/ static boolean nIsRect(long nPath, RectF rect) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return false; - } - - // create an Area that can test if the path is a rect - Area area = new Area(pathDelegate.mPath); - if (area.isRectangular()) { - if (rect != null) { - pathDelegate.fillBounds(rect); - } - - return true; - } - - return false; - } - - @LayoutlibDelegate - /*package*/ static void nComputeBounds(long nPath, RectF bounds) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.fillBounds(bounds); - } - - @LayoutlibDelegate - /*package*/ static void nIncReserve(long nPath, int extraPtCount) { - // since we use a java2D path, there's no way to pre-allocate new points, - // so we do nothing. - } - - @LayoutlibDelegate - /*package*/ static void nMoveTo(long nPath, float x, float y) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.moveTo(x, y); - } - - @LayoutlibDelegate - /*package*/ static void nRMoveTo(long nPath, float dx, float dy) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.rMoveTo(dx, dy); - } - - @LayoutlibDelegate - /*package*/ static void nLineTo(long nPath, float x, float y) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.lineTo(x, y); - } - - @LayoutlibDelegate - /*package*/ static void nRLineTo(long nPath, float dx, float dy) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.rLineTo(dx, dy); - } - - @LayoutlibDelegate - /*package*/ static void nQuadTo(long nPath, float x1, float y1, float x2, float y2) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.quadTo(x1, y1, x2, y2); - } - - @LayoutlibDelegate - /*package*/ static void nRQuadTo(long nPath, float dx1, float dy1, float dx2, float dy2) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.rQuadTo(dx1, dy1, dx2, dy2); - } - - @LayoutlibDelegate - /*package*/ static void nCubicTo(long nPath, float x1, float y1, - float x2, float y2, float x3, float y3) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.cubicTo(x1, y1, x2, y2, x3, y3); - } - - @LayoutlibDelegate - /*package*/ static void nRCubicTo(long nPath, float x1, float y1, - float x2, float y2, float x3, float y3) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.rCubicTo(x1, y1, x2, y2, x3, y3); - } - - @LayoutlibDelegate - /*package*/ static void nArcTo(long nPath, float left, float top, float right, - float bottom, - float startAngle, float sweepAngle, boolean forceMoveTo) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.arcTo(left, top, right, bottom, startAngle, sweepAngle, forceMoveTo); - } - - @LayoutlibDelegate - /*package*/ static void nClose(long nPath) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.close(); - } - - @LayoutlibDelegate - /*package*/ static void nAddRect(long nPath, - float left, float top, float right, float bottom, int dir) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.addRect(left, top, right, bottom, dir); - } - - @LayoutlibDelegate - /*package*/ static void nAddOval(long nPath, float left, float top, float right, - float bottom, int dir) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.mPath.append(new Ellipse2D.Float( - left, top, right - left, bottom - top), false); - } - - @LayoutlibDelegate - /*package*/ static void nAddCircle(long nPath, float x, float y, float radius, int dir) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - // because x/y is the center of the circle, need to offset this by the radius - pathDelegate.mPath.append(new Ellipse2D.Float( - x - radius, y - radius, radius * 2, radius * 2), false); - } - - @LayoutlibDelegate - /*package*/ static void nAddArc(long nPath, float left, float top, float right, - float bottom, float startAngle, float sweepAngle) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - // because x/y is the center of the circle, need to offset this by the radius - pathDelegate.mPath.append(new Arc2D.Float( - left, top, right - left, bottom - top, - -startAngle, -sweepAngle, Arc2D.OPEN), false); - } - - @LayoutlibDelegate - /*package*/ static void nAddRoundRect(long nPath, float left, float top, float right, - float bottom, float rx, float ry, int dir) { - - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.mPath.append(new RoundRectangle2D.Float( - left, top, right - left, bottom - top, rx * 2, ry * 2), false); - } - - @LayoutlibDelegate - /*package*/ static void nAddRoundRect(long nPath, float left, float top, float right, - float bottom, float[] radii, int dir) { - - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - float[] cornerDimensions = new float[radii.length]; - for (int i = 0; i < radii.length; i++) { - cornerDimensions[i] = 2 * radii[i]; - } - pathDelegate.mPath.append(new RoundRectangle(left, top, right - left, bottom - top, - cornerDimensions), false); - } - - @LayoutlibDelegate - /*package*/ static void nAddPath(long nPath, long src, float dx, float dy) { - addPath(nPath, src, AffineTransform.getTranslateInstance(dx, dy)); - } - - @LayoutlibDelegate - /*package*/ static void nAddPath(long nPath, long src) { - addPath(nPath, src, null /*transform*/); - } - - @LayoutlibDelegate - /*package*/ static void nAddPath(long nPath, long src, long matrix) { - Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(matrix); - if (matrixDelegate == null) { - return; - } - - addPath(nPath, src, matrixDelegate.getAffineTransform()); - } - - @LayoutlibDelegate - /*package*/ static void nOffset(long nPath, float dx, float dy) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.offset(dx, dy); - } - - @LayoutlibDelegate - /*package*/ static void nSetLastPoint(long nPath, float dx, float dy) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.mLastX = dx; - pathDelegate.mLastY = dy; - } - - @LayoutlibDelegate - /*package*/ static void nTransform(long nPath, long matrix, - long dst_path) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(matrix); - if (matrixDelegate == null) { - return; - } - - // this can be null if dst_path is 0 - Path_Delegate dstDelegate = sManager.getDelegate(dst_path); - - pathDelegate.transform(matrixDelegate, dstDelegate); - } - - @LayoutlibDelegate - /*package*/ static void nTransform(long nPath, long matrix) { - nTransform(nPath, matrix, 0); - } - - @LayoutlibDelegate - /*package*/ static boolean nOp(long nPath1, long nPath2, int op, long result) { - Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, "Path.op() not supported", null); - return false; - } - - @LayoutlibDelegate - /*package*/ static void nFinalize(long nPath) { - sManager.removeJavaReferenceFor(nPath); - } - - @LayoutlibDelegate - /*package*/ static float[] nApproximate(long nPath, float error) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return null; - } - // Get a FlatteningIterator - PathIterator iterator = pathDelegate.getJavaShape().getPathIterator(null, error); - - float segment[] = new float[6]; - float totalLength = 0; - ArrayList<Point2D.Float> points = new ArrayList<Point2D.Float>(); - Point2D.Float previousPoint = null; - while (!iterator.isDone()) { - int type = iterator.currentSegment(segment); - Point2D.Float currentPoint = new Point2D.Float(segment[0], segment[1]); - // MoveTo shouldn't affect the length - if (previousPoint != null && type != PathIterator.SEG_MOVETO) { - totalLength += currentPoint.distance(previousPoint); - } - previousPoint = currentPoint; - points.add(currentPoint); - iterator.next(); - } - - int nPoints = points.size(); - float[] result = new float[nPoints * 3]; - previousPoint = null; - for (int i = 0; i < nPoints; i++) { - Point2D.Float point = points.get(i); - float distance = previousPoint != null ? (float) previousPoint.distance(point) : .0f; - result[i * 3] = distance / totalLength; - result[i * 3 + 1] = point.x; - result[i * 3 + 2] = point.y; - - totalLength += distance; - previousPoint = point; - } - - return result; - } - - // ---- Private helper methods ---- - - private void set(Path_Delegate delegate) { - mPath.reset(); - setFillType(delegate.mFillType); - mPath.append(delegate.mPath, false /*connect*/); - } - - private void setFillType(FillType fillType) { - mFillType = fillType; - mPath.setWindingRule(getWindingRule(fillType)); - } - - /** - * Returns the Java2D winding rules matching a given Android {@link FillType}. - * @param type the android fill type - * @return the matching java2d winding rule. - */ - private static int getWindingRule(FillType type) { - switch (type) { - case WINDING: - case INVERSE_WINDING: - return GeneralPath.WIND_NON_ZERO; - case EVEN_ODD: - case INVERSE_EVEN_ODD: - return GeneralPath.WIND_EVEN_ODD; - - default: - assert false; - return GeneralPath.WIND_NON_ZERO; - } - } - - @NonNull - private static Direction getDirection(int direction) { - for (Direction d : Direction.values()) { - if (direction == d.nativeInt) { - return d; - } - } - - assert false; - return null; - } - - public static void addPath(long destPath, long srcPath, AffineTransform transform) { - Path_Delegate destPathDelegate = sManager.getDelegate(destPath); - if (destPathDelegate == null) { - return; - } - - Path_Delegate srcPathDelegate = sManager.getDelegate(srcPath); - if (srcPathDelegate == null) { - return; - } - - if (transform != null) { - destPathDelegate.mPath.append( - srcPathDelegate.mPath.getPathIterator(transform), false); - } else { - destPathDelegate.mPath.append(srcPathDelegate.mPath, false); - } - } - - - /** - * Returns whether the path already contains any points. - * Note that this is different to - * {@link #isEmpty} because if all elements are {@link PathIterator#SEG_MOVETO}, - * {@link #isEmpty} will return true while hasPoints will return false. - */ - public boolean hasPoints() { - return !mPath.getPathIterator(null).isDone(); - } - - /** - * Returns whether the path is empty (contains no lines or curves). - * @see Path#isEmpty - */ - public boolean isEmpty() { - if (!mCachedIsEmpty) { - return false; - } - - float[] coords = new float[6]; - mCachedIsEmpty = Boolean.TRUE; - for (PathIterator it = mPath.getPathIterator(null); !it.isDone(); it.next()) { - int type = it.currentSegment(coords); - if (type != PathIterator.SEG_MOVETO) { - // Once we know that the path is not empty, we do not need to check again unless - // Path#reset is called. - mCachedIsEmpty = false; - return false; - } - } - - return true; - } - - /** - * Fills the given {@link RectF} with the path bounds. - * @param bounds the RectF to be filled. - */ - public void fillBounds(RectF bounds) { - Rectangle2D rect = mPath.getBounds2D(); - bounds.left = (float)rect.getMinX(); - bounds.right = (float)rect.getMaxX(); - bounds.top = (float)rect.getMinY(); - bounds.bottom = (float)rect.getMaxY(); - } - - /** - * Set the beginning of the next contour to the point (x,y). - * - * @param x The x-coordinate of the start of a new contour - * @param y The y-coordinate of the start of a new contour - */ - public void moveTo(float x, float y) { - mPath.moveTo(mLastX = x, mLastY = y); - } - - /** - * Set the beginning of the next contour relative to the last point on the - * previous contour. If there is no previous contour, this is treated the - * same as moveTo(). - * - * @param dx The amount to add to the x-coordinate of the end of the - * previous contour, to specify the start of a new contour - * @param dy The amount to add to the y-coordinate of the end of the - * previous contour, to specify the start of a new contour - */ - public void rMoveTo(float dx, float dy) { - dx += mLastX; - dy += mLastY; - mPath.moveTo(mLastX = dx, mLastY = dy); - } - - /** - * Add a line from the last point to the specified point (x,y). - * If no moveTo() call has been made for this contour, the first point is - * automatically set to (0,0). - * - * @param x The x-coordinate of the end of a line - * @param y The y-coordinate of the end of a line - */ - public void lineTo(float x, float y) { - if (!hasPoints()) { - mPath.moveTo(mLastX = 0, mLastY = 0); - } - mPath.lineTo(mLastX = x, mLastY = y); - } - - /** - * Same as lineTo, but the coordinates are considered relative to the last - * point on this contour. If there is no previous point, then a moveTo(0,0) - * is inserted automatically. - * - * @param dx The amount to add to the x-coordinate of the previous point on - * this contour, to specify a line - * @param dy The amount to add to the y-coordinate of the previous point on - * this contour, to specify a line - */ - public void rLineTo(float dx, float dy) { - if (!hasPoints()) { - mPath.moveTo(mLastX = 0, mLastY = 0); - } - - if (Math.abs(dx) < EPSILON && Math.abs(dy) < EPSILON) { - // The delta is so small that this shouldn't generate a line - return; - } - - dx += mLastX; - dy += mLastY; - mPath.lineTo(mLastX = dx, mLastY = dy); - } - - /** - * Add a quadratic bezier from the last point, approaching control point - * (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for - * this contour, the first point is automatically set to (0,0). - * - * @param x1 The x-coordinate of the control point on a quadratic curve - * @param y1 The y-coordinate of the control point on a quadratic curve - * @param x2 The x-coordinate of the end point on a quadratic curve - * @param y2 The y-coordinate of the end point on a quadratic curve - */ - public void quadTo(float x1, float y1, float x2, float y2) { - mPath.quadTo(x1, y1, mLastX = x2, mLastY = y2); - } - - /** - * Same as quadTo, but the coordinates are considered relative to the last - * point on this contour. If there is no previous point, then a moveTo(0,0) - * is inserted automatically. - * - * @param dx1 The amount to add to the x-coordinate of the last point on - * this contour, for the control point of a quadratic curve - * @param dy1 The amount to add to the y-coordinate of the last point on - * this contour, for the control point of a quadratic curve - * @param dx2 The amount to add to the x-coordinate of the last point on - * this contour, for the end point of a quadratic curve - * @param dy2 The amount to add to the y-coordinate of the last point on - * this contour, for the end point of a quadratic curve - */ - public void rQuadTo(float dx1, float dy1, float dx2, float dy2) { - if (!hasPoints()) { - mPath.moveTo(mLastX = 0, mLastY = 0); - } - dx1 += mLastX; - dy1 += mLastY; - dx2 += mLastX; - dy2 += mLastY; - mPath.quadTo(dx1, dy1, mLastX = dx2, mLastY = dy2); - } - - /** - * Add a cubic bezier from the last point, approaching control points - * (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been - * made for this contour, the first point is automatically set to (0,0). - * - * @param x1 The x-coordinate of the 1st control point on a cubic curve - * @param y1 The y-coordinate of the 1st control point on a cubic curve - * @param x2 The x-coordinate of the 2nd control point on a cubic curve - * @param y2 The y-coordinate of the 2nd control point on a cubic curve - * @param x3 The x-coordinate of the end point on a cubic curve - * @param y3 The y-coordinate of the end point on a cubic curve - */ - public void cubicTo(float x1, float y1, float x2, float y2, - float x3, float y3) { - if (!hasPoints()) { - mPath.moveTo(0, 0); - } - mPath.curveTo(x1, y1, x2, y2, mLastX = x3, mLastY = y3); - } - - /** - * Same as cubicTo, but the coordinates are considered relative to the - * current point on this contour. If there is no previous point, then a - * moveTo(0,0) is inserted automatically. - */ - public void rCubicTo(float dx1, float dy1, float dx2, float dy2, - float dx3, float dy3) { - if (!hasPoints()) { - mPath.moveTo(mLastX = 0, mLastY = 0); - } - dx1 += mLastX; - dy1 += mLastY; - dx2 += mLastX; - dy2 += mLastY; - dx3 += mLastX; - dy3 += mLastY; - mPath.curveTo(dx1, dy1, dx2, dy2, mLastX = dx3, mLastY = dy3); - } - - /** - * Append the specified arc to the path as a new contour. If the start of - * the path is different from the path's current last point, then an - * automatic lineTo() is added to connect the current contour to the - * start of the arc. However, if the path is empty, then we call moveTo() - * with the first point of the arc. The sweep angle is tread mod 360. - * - * @param left The left of oval defining shape and size of the arc - * @param top The top of oval defining shape and size of the arc - * @param right The right of oval defining shape and size of the arc - * @param bottom The bottom of oval defining shape and size of the arc - * @param startAngle Starting angle (in degrees) where the arc begins - * @param sweepAngle Sweep angle (in degrees) measured clockwise, treated - * mod 360. - * @param forceMoveTo If true, always begin a new contour with the arc - */ - public void arcTo(float left, float top, float right, float bottom, float startAngle, - float sweepAngle, - boolean forceMoveTo) { - Arc2D arc = new Arc2D.Float(left, top, right - left, bottom - top, -startAngle, - -sweepAngle, Arc2D.OPEN); - mPath.append(arc, true /*connect*/); - - resetLastPointFromPath(); - } - - /** - * Close the current contour. If the current point is not equal to the - * first point of the contour, a line segment is automatically added. - */ - public void close() { - mPath.closePath(); - } - - private void resetLastPointFromPath() { - Point2D last = mPath.getCurrentPoint(); - mLastX = (float) last.getX(); - mLastY = (float) last.getY(); - } - - /** - * Add a closed rectangle contour to the path - * - * @param left The left side of a rectangle to add to the path - * @param top The top of a rectangle to add to the path - * @param right The right side of a rectangle to add to the path - * @param bottom The bottom of a rectangle to add to the path - * @param dir The direction to wind the rectangle's contour - */ - public void addRect(float left, float top, float right, float bottom, - int dir) { - moveTo(left, top); - - Direction direction = getDirection(dir); - - switch (direction) { - case CW: - lineTo(right, top); - lineTo(right, bottom); - lineTo(left, bottom); - break; - case CCW: - lineTo(left, bottom); - lineTo(right, bottom); - lineTo(right, top); - break; - } - - close(); - - resetLastPointFromPath(); - } - - /** - * Offset the path by (dx,dy), returning true on success - * - * @param dx The amount in the X direction to offset the entire path - * @param dy The amount in the Y direction to offset the entire path - */ - public void offset(float dx, float dy) { - GeneralPath newPath = new GeneralPath(); - - PathIterator iterator = mPath.getPathIterator(new AffineTransform(0, 0, dx, 0, 0, dy)); - - newPath.append(iterator, false /*connect*/); - mPath = newPath; - } - - /** - * Transform the points in this path by matrix, and write the answer - * into dst. If dst is null, then the the original path is modified. - * - * @param matrix The matrix to apply to the path - * @param dst The transformed path is written here. If dst is null, - * then the the original path is modified - */ - public void transform(Matrix_Delegate matrix, Path_Delegate dst) { - if (matrix.hasPerspective()) { - assert false; - Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_AFFINE, - "android.graphics.Path#transform() only " + - "supports affine transformations.", null, null /*data*/); - } - - GeneralPath newPath = new GeneralPath(); - - PathIterator iterator = mPath.getPathIterator(matrix.getAffineTransform()); - - newPath.append(iterator, false /*connect*/); - - if (dst != null) { - dst.mPath = newPath; - } else { - mPath = newPath; - } - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java deleted file mode 100644 index ff3f19f3f742..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.graphics.PorterDuff.Mode; - -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; - -import static com.android.layoutlib.bridge.impl.PorterDuffUtility.getComposite; -import static com.android.layoutlib.bridge.impl.PorterDuffUtility.getPorterDuffMode; - -/** - * Delegate implementing the native methods of android.graphics.PorterDuffColorFilter - * - * Through the layoutlib_create tool, the original native methods of PorterDuffColorFilter 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 PorterDuffColorFilter class. - * - * Because this extends {@link ColorFilter_Delegate}, there's no need to use a - * {@link DelegateManager}, as all the Shader classes will be added to the manager - * owned by {@link ColorFilter_Delegate}. - * - * @see ColorFilter_Delegate - * - */ -public class PorterDuffColorFilter_Delegate extends ColorFilter_Delegate { - - // ---- delegate data ---- - - private final java.awt.Color mSrcColor; - private final Mode mMode; - - - // ---- Public Helper methods ---- - - @Override - public boolean isSupported() { - return true; - } - - @Override - public String getSupportMessage() { - return "PorterDuff Color Filter is not supported for mode: " + mMode.name() + "."; - } - - @Override - public void applyFilter(Graphics2D g, int width, int height) { - g.setComposite(getComposite(mMode, 0xFF)); - g.setColor(mSrcColor); - g.fillRect(0, 0, width, height); - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static long native_CreatePorterDuffFilter(int srcColor, int porterDuffMode) { - PorterDuffColorFilter_Delegate newDelegate = - new PorterDuffColorFilter_Delegate(srcColor, porterDuffMode); - return sManager.addNewDelegate(newDelegate); - } - - - // ---- Private delegate/helper methods ---- - - private PorterDuffColorFilter_Delegate(int srcColor, int mode) { - mSrcColor = new java.awt.Color(srcColor, true /* hasAlpha */); - mMode = getCompatibleMode(getPorterDuffMode(mode)); - } - - // For filtering the colors, the src image should contain the "color" only for pixel values - // which are not transparent in the target image. But, we are using a simple rectangular image - // completely filled with color. Hence some Composite rules do not apply as intended. However, - // in such cases, they can usually be mapped to some other mode, which produces an approximately - // equivalent result. - private Mode getCompatibleMode(Mode mode) { - Mode m = mode; - // Modes that are directly supported: - // CLEAR, DST, SRC_IN, DST_IN, DST_OUT, SRC_ATOP, DARKEN, LIGHTEN, MULTIPLY, SCREEN, - // ADD, OVERLAY - switch (mode) { - // Modes that can be mapped to one of the supported modes. - case SRC: - m = Mode.SRC_IN; - break; - case SRC_OVER: - m = Mode.SRC_ATOP; - break; - case DST_OVER: - m = Mode.DST; - break; - case SRC_OUT: - m = Mode.CLEAR; - break; - case DST_ATOP: - m = Mode.DST_IN; - break; - case XOR: - m = Mode.DST_OUT; - break; - } - return m; - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java deleted file mode 100644 index b5ba46830a25..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.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.graphics.Shader.TileMode; - -import java.awt.image.ColorModel; - -/** - * Delegate implementing the native methods of android.graphics.RadialGradient - * - * Through the layoutlib_create tool, the original native methods of RadialGradient 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 RadialGradient class. - * - * Because this extends {@link Shader_Delegate}, there's no need to use a {@link DelegateManager}, - * as all the Shader classes will be added to the manager owned by {@link Shader_Delegate}. - * - * @see Shader_Delegate - * - */ -public class RadialGradient_Delegate extends Gradient_Delegate { - - // ---- delegate data ---- - private java.awt.Paint mJavaPaint; - - // ---- Public Helper methods ---- - - @Override - public java.awt.Paint getJavaPaint() { - return mJavaPaint; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static long nativeCreate1(long matrix, float x, float y, float radius, - int colors[], float positions[], int tileMode) { - RadialGradient_Delegate newDelegate = new RadialGradient_Delegate(matrix, x, y, radius, - colors, positions, Shader_Delegate.getTileMode(tileMode)); - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static long nativeCreate2(long matrix, float x, float y, float radius, - int color0, int color1, int tileMode) { - return nativeCreate1(matrix, x, y, radius, new int[] { color0, color1 }, - null /*positions*/, tileMode); - } - - // ---- Private delegate/helper methods ---- - - /** - * Create a shader that draws a radial gradient given the center and radius. - * - * @param nativeMatrix reference to the shader's native transformation matrix - * @param x The x-coordinate of the center of the radius - * @param y The y-coordinate of the center of the radius - * @param radius Must be positive. The radius of the circle for this - * gradient - * @param colors The colors to be distributed between the center and edge of - * the circle - * @param positions May be NULL. The relative position of each corresponding - * color in the colors array. If this is NULL, the the colors are - * distributed evenly between the center and edge of the circle. - * @param tile The Shader tiling mode - */ - private RadialGradient_Delegate(long nativeMatrix, float x, float y, float radius, - int colors[], float positions[], TileMode tile) { - super(nativeMatrix, colors, positions); - mJavaPaint = new RadialGradientPaint(x, y, radius, mColors, mPositions, tile); - } - - private class RadialGradientPaint extends GradientPaint { - - private final float mX; - private final float mY; - private final float mRadius; - - public RadialGradientPaint(float x, float y, float radius, - int[] colors, float[] positions, TileMode mode) { - super(colors, positions, mode); - mX = x; - mY = y; - mRadius = radius; - } - - @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) { - precomputeGradientColors(); - - java.awt.geom.AffineTransform canvasMatrix; - try { - canvasMatrix = xform.createInverse(); - } catch (java.awt.geom.NoninvertibleTransformException e) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE, - "Unable to inverse matrix in RadialGradient", e, null /*data*/); - canvasMatrix = new java.awt.geom.AffineTransform(); - } - - java.awt.geom.AffineTransform localMatrix = getLocalMatrix(); - try { - localMatrix = localMatrix.createInverse(); - } catch (java.awt.geom.NoninvertibleTransformException e) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE, - "Unable to inverse matrix in RadialGradient", e, null /*data*/); - localMatrix = new java.awt.geom.AffineTransform(); - } - - return new RadialGradientPaintContext(canvasMatrix, localMatrix, colorModel); - } - - private class RadialGradientPaintContext implements java.awt.PaintContext { - - private final java.awt.geom.AffineTransform mCanvasMatrix; - private final java.awt.geom.AffineTransform mLocalMatrix; - private final java.awt.image.ColorModel mColorModel; - - public RadialGradientPaintContext( - java.awt.geom.AffineTransform canvasMatrix, - java.awt.geom.AffineTransform localMatrix, - java.awt.image.ColorModel colorModel) { - mCanvasMatrix = canvasMatrix; - mLocalMatrix = localMatrix; - mColorModel = colorModel.hasAlpha() ? colorModel : ColorModel.getRGBdefault(); - } - - @Override - public void dispose() { - } - - @Override - public java.awt.image.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( - mColorModel, mColorModel.createCompatibleWritableRaster(w, h), - mColorModel.isAlphaPremultiplied(), null); - - int[] data = new int[w*h]; - - // compute distance from each point to the center, and figure out the distance from - // it. - int index = 0; - float[] pt1 = new float[2]; - float[] pt2 = new float[2]; - for (int iy = 0 ; iy < h ; iy++) { - for (int ix = 0 ; ix < w ; ix++) { - // handle the canvas transform - pt1[0] = x + ix; - pt1[1] = y + iy; - mCanvasMatrix.transform(pt1, 0, pt2, 0, 1); - - // handle the local matrix - pt1[0] = pt2[0] - mX; - pt1[1] = pt2[1] - mY; - mLocalMatrix.transform(pt1, 0, pt2, 0, 1); - - float _x = pt2[0]; - float _y = pt2[1]; - float distance = (float) Math.hypot(_x, _y); - - data[index++] = getGradientColor(distance / mRadius); - } - } - - image.setRGB(0 /*startX*/, 0 /*startY*/, w, h, data, 0 /*offset*/, w /*scansize*/); - - return image.getRaster(); - } - - } - } - -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java deleted file mode 100644 index edb7025b7cd7..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java +++ /dev/null @@ -1,483 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.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.os.Parcel; - -import java.awt.Rectangle; -import java.awt.Shape; -import java.awt.geom.AffineTransform; -import java.awt.geom.Area; -import java.awt.geom.Rectangle2D; - -/** - * Delegate implementing the native methods of android.graphics.Region - * - * Through the layoutlib_create tool, the original native methods of Region 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 Region class. - * - * This also serve as a base class for all Region delegate classes. - * - * @see DelegateManager - * - */ -public class Region_Delegate { - - // ---- delegate manager ---- - protected static final DelegateManager<Region_Delegate> sManager = - new DelegateManager<Region_Delegate>(Region_Delegate.class); - - // ---- delegate helper data ---- - - // ---- delegate data ---- - private Area mArea = new Area(); - - // ---- Public Helper methods ---- - - public static Region_Delegate getDelegate(long nativeShader) { - return sManager.getDelegate(nativeShader); - } - - public Area getJavaArea() { - return mArea; - } - - /** - * Combines two {@link Shape} into another one (actually an {@link Area}), according - * to the given {@link Region.Op}. - * - * If the Op is not one that combines two shapes, then this return null - * - * @param shape1 the firt shape to combine which can be null if there's no original clip. - * @param shape2 the 2nd shape to combine - * @param regionOp the operande for the combine - * @return a new area or null. - */ - public static Area combineShapes(Shape shape1, Shape shape2, int regionOp) { - if (regionOp == Region.Op.DIFFERENCE.nativeInt) { - // if shape1 is null (empty), then the result is null. - if (shape1 == null) { - return null; - } - - // result is always a new area. - Area result = new Area(shape1); - result.subtract(shape2 instanceof Area ? (Area) shape2 : new Area(shape2)); - return result; - - } else if (regionOp == Region.Op.INTERSECT.nativeInt) { - // if shape1 is null, then the result is simply shape2. - if (shape1 == null) { - return new Area(shape2); - } - - // result is always a new area. - Area result = new Area(shape1); - result.intersect(shape2 instanceof Area ? (Area) shape2 : new Area(shape2)); - return result; - - } else if (regionOp == Region.Op.UNION.nativeInt) { - // if shape1 is null, then the result is simply shape2. - if (shape1 == null) { - return new Area(shape2); - } - - // result is always a new area. - Area result = new Area(shape1); - result.add(shape2 instanceof Area ? (Area) shape2 : new Area(shape2)); - return result; - - } else if (regionOp == Region.Op.XOR.nativeInt) { - // if shape1 is null, then the result is simply shape2 - if (shape1 == null) { - return new Area(shape2); - } - - // result is always a new area. - Area result = new Area(shape1); - result.exclusiveOr(shape2 instanceof Area ? (Area) shape2 : new Area(shape2)); - return result; - - } else if (regionOp == Region.Op.REVERSE_DIFFERENCE.nativeInt) { - // result is always a new area. - Area result = new Area(shape2); - - if (shape1 != null) { - result.subtract(shape1 instanceof Area ? (Area) shape1 : new Area(shape1)); - } - - return result; - } - - return null; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static boolean isEmpty(Region thisRegion) { - Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion); - if (regionDelegate == null) { - return true; - } - - return regionDelegate.mArea.isEmpty(); - } - - @LayoutlibDelegate - /*package*/ static boolean isRect(Region thisRegion) { - Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion); - if (regionDelegate == null) { - return true; - } - - return regionDelegate.mArea.isRectangular(); - } - - @LayoutlibDelegate - /*package*/ static boolean isComplex(Region thisRegion) { - Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion); - if (regionDelegate == null) { - return true; - } - - return regionDelegate.mArea.isSingular() == false; - } - - @LayoutlibDelegate - /*package*/ static boolean contains(Region thisRegion, int x, int y) { - Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion); - if (regionDelegate == null) { - return false; - } - - return regionDelegate.mArea.contains(x, y); - } - - @LayoutlibDelegate - /*package*/ static boolean quickContains(Region thisRegion, - int left, int top, int right, int bottom) { - Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion); - if (regionDelegate == null) { - return false; - } - - return regionDelegate.mArea.isRectangular() && - regionDelegate.mArea.contains(left, top, right - left, bottom - top); - } - - @LayoutlibDelegate - /*package*/ static boolean quickReject(Region thisRegion, - int left, int top, int right, int bottom) { - Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion); - if (regionDelegate == null) { - return false; - } - - return regionDelegate.mArea.isEmpty() || - regionDelegate.mArea.intersects(left, top, right - left, bottom - top) == false; - } - - @LayoutlibDelegate - /*package*/ static boolean quickReject(Region thisRegion, Region rgn) { - Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion); - if (regionDelegate == null) { - return false; - } - - Region_Delegate targetRegionDelegate = sManager.getDelegate(rgn.mNativeRegion); - if (targetRegionDelegate == null) { - return false; - } - - return regionDelegate.mArea.isEmpty() || - regionDelegate.mArea.getBounds().intersects( - targetRegionDelegate.mArea.getBounds()) == false; - - } - - @LayoutlibDelegate - /*package*/ static void translate(Region thisRegion, int dx, int dy, Region dst) { - Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion); - if (regionDelegate == null) { - return; - } - - Region_Delegate targetRegionDelegate = sManager.getDelegate(dst.mNativeRegion); - if (targetRegionDelegate == null) { - return; - } - - if (regionDelegate.mArea.isEmpty()) { - targetRegionDelegate.mArea = new Area(); - } else { - targetRegionDelegate.mArea = new Area(regionDelegate.mArea); - AffineTransform mtx = new AffineTransform(); - mtx.translate(dx, dy); - targetRegionDelegate.mArea.transform(mtx); - } - } - - @LayoutlibDelegate - /*package*/ static void scale(Region thisRegion, float scale, Region dst) { - Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion); - if (regionDelegate == null) { - return; - } - - Region_Delegate targetRegionDelegate = sManager.getDelegate(dst.mNativeRegion); - if (targetRegionDelegate == null) { - return; - } - - if (regionDelegate.mArea.isEmpty()) { - targetRegionDelegate.mArea = new Area(); - } else { - targetRegionDelegate.mArea = new Area(regionDelegate.mArea); - AffineTransform mtx = new AffineTransform(); - mtx.scale(scale, scale); - targetRegionDelegate.mArea.transform(mtx); - } - } - - @LayoutlibDelegate - /*package*/ static long nativeConstructor() { - Region_Delegate newDelegate = new Region_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static void nativeDestructor(long native_region) { - sManager.removeJavaReferenceFor(native_region); - } - - @LayoutlibDelegate - /*package*/ static void nativeSetRegion(long native_dst, long native_src) { - Region_Delegate dstRegion = sManager.getDelegate(native_dst); - if (dstRegion == null) { - return; - } - - Region_Delegate srcRegion = sManager.getDelegate(native_src); - if (srcRegion == null) { - return; - } - - dstRegion.mArea.reset(); - dstRegion.mArea.add(srcRegion.mArea); - - } - - @LayoutlibDelegate - /*package*/ static boolean nativeSetRect(long native_dst, - int left, int top, int right, int bottom) { - Region_Delegate dstRegion = sManager.getDelegate(native_dst); - if (dstRegion == null) { - return true; - } - - dstRegion.mArea = new Area(new Rectangle2D.Float(left, top, right - left, bottom - top)); - return dstRegion.mArea.getBounds().isEmpty() == false; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeSetPath(long native_dst, long native_path, long native_clip) { - Region_Delegate dstRegion = sManager.getDelegate(native_dst); - if (dstRegion == null) { - return true; - } - - Path_Delegate path = Path_Delegate.getDelegate(native_path); - if (path == null) { - return true; - } - - dstRegion.mArea = new Area(path.getJavaShape()); - - Region_Delegate clip = sManager.getDelegate(native_clip); - if (clip != null) { - dstRegion.mArea.subtract(clip.getJavaArea()); - } - - return dstRegion.mArea.getBounds().isEmpty() == false; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeGetBounds(long native_region, Rect rect) { - Region_Delegate region = sManager.getDelegate(native_region); - if (region == null) { - return true; - } - - Rectangle bounds = region.mArea.getBounds(); - if (bounds.isEmpty()) { - rect.left = rect.top = rect.right = rect.bottom = 0; - return false; - } - - rect.left = bounds.x; - rect.top = bounds.y; - rect.right = bounds.x + bounds.width; - rect.bottom = bounds.y + bounds.height; - return true; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeGetBoundaryPath(long native_region, long native_path) { - Region_Delegate region = sManager.getDelegate(native_region); - if (region == null) { - return false; - } - - Path_Delegate path = Path_Delegate.getDelegate(native_path); - if (path == null) { - return false; - } - - if (region.mArea.isEmpty()) { - path.reset(); - return false; - } - - path.setPathIterator(region.mArea.getPathIterator(new AffineTransform())); - return true; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeOp(long native_dst, - int left, int top, int right, int bottom, int op) { - Region_Delegate region = sManager.getDelegate(native_dst); - if (region == null) { - return false; - } - - region.mArea = combineShapes(region.mArea, - new Rectangle2D.Float(left, top, right - left, bottom - top), op); - - assert region.mArea != null; - if (region.mArea != null) { - region.mArea = new Area(); - } - - return region.mArea.getBounds().isEmpty() == false; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeOp(long native_dst, Rect rect, long native_region, int op) { - Region_Delegate region = sManager.getDelegate(native_dst); - if (region == null) { - return false; - } - - region.mArea = combineShapes(region.mArea, - new Rectangle2D.Float(rect.left, rect.top, rect.width(), rect.height()), op); - - assert region.mArea != null; - if (region.mArea != null) { - region.mArea = new Area(); - } - - return region.mArea.getBounds().isEmpty() == false; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeOp(long native_dst, - long native_region1, long native_region2, int op) { - Region_Delegate dstRegion = sManager.getDelegate(native_dst); - if (dstRegion == null) { - return true; - } - - Region_Delegate region1 = sManager.getDelegate(native_region1); - if (region1 == null) { - return false; - } - - Region_Delegate region2 = sManager.getDelegate(native_region2); - if (region2 == null) { - return false; - } - - dstRegion.mArea = combineShapes(region1.mArea, region2.mArea, op); - - assert dstRegion.mArea != null; - if (dstRegion.mArea != null) { - dstRegion.mArea = new Area(); - } - - return dstRegion.mArea.getBounds().isEmpty() == false; - - } - - @LayoutlibDelegate - /*package*/ static long nativeCreateFromParcel(Parcel p) { - // This is only called by Region.CREATOR (Parcelable.Creator<Region>), which is only - // used during aidl call so really this should not be called. - Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, - "AIDL is not suppored, and therefore Regions cannot be created from parcels.", - null /*data*/); - return 0; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeWriteToParcel(long native_region, - Parcel p) { - // This is only called when sending a region through aidl, so really this should not - // be called. - Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, - "AIDL is not suppored, and therefore Regions cannot be written to parcels.", - null /*data*/); - return false; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeEquals(long native_r1, long native_r2) { - Region_Delegate region1 = sManager.getDelegate(native_r1); - if (region1 == null) { - return false; - } - - Region_Delegate region2 = sManager.getDelegate(native_r2); - if (region2 == null) { - return false; - } - - return region1.mArea.equals(region2.mArea); - } - - @LayoutlibDelegate - /*package*/ static String nativeToString(long native_region) { - Region_Delegate region = sManager.getDelegate(native_region); - if (region == null) { - return "not found"; - } - - return region.mArea.toString(); - } - - // ---- Private delegate/helper methods ---- - -} diff --git a/tools/layoutlib/bridge/src/android/graphics/RoundRectangle.java b/tools/layoutlib/bridge/src/android/graphics/RoundRectangle.java deleted file mode 100644 index 736f03ec5a8c..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/RoundRectangle.java +++ /dev/null @@ -1,368 +0,0 @@ -/* - * 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 android.graphics; - -import java.awt.geom.AffineTransform; -import java.awt.geom.PathIterator; -import java.awt.geom.Rectangle2D; -import java.awt.geom.RectangularShape; -import java.awt.geom.RoundRectangle2D; -import java.util.EnumSet; -import java.util.NoSuchElementException; - -/** - * Defines a rectangle with rounded corners, where the sizes of the corners - * are potentially different. - */ -public class RoundRectangle extends RectangularShape { - public double x; - public double y; - public double width; - public double height; - public double ulWidth; - public double ulHeight; - public double urWidth; - public double urHeight; - public double lrWidth; - public double lrHeight; - public double llWidth; - public double llHeight; - - private enum Zone { - CLOSE_OUTSIDE, - CLOSE_INSIDE, - MIDDLE, - FAR_INSIDE, - FAR_OUTSIDE - } - - private final EnumSet<Zone> close = EnumSet.of(Zone.CLOSE_OUTSIDE, Zone.CLOSE_INSIDE); - private final EnumSet<Zone> far = EnumSet.of(Zone.FAR_OUTSIDE, Zone.FAR_INSIDE); - - /** - * @param cornerDimensions array of 8 floating-point number corresponding to the width and - * the height of each corner in the following order: upper-left, upper-right, lower-right, - * lower-left. It assumes for the size the same convention as {@link RoundRectangle2D}, that - * is that the width and height of a corner correspond to the total width and height of the - * ellipse that corner is a quarter of. - */ - public RoundRectangle(float x, float y, float width, float height, float[] cornerDimensions) { - assert cornerDimensions.length == 8 : "The array of corner dimensions must have eight " + - "elements"; - - this.x = x; - this.y = y; - this.width = width; - this.height = height; - - float[] dimensions = cornerDimensions.clone(); - // If a value is negative, the corresponding corner is squared - for (int i = 0; i < dimensions.length; i += 2) { - if (dimensions[i] < 0 || dimensions[i + 1] < 0) { - dimensions[i] = 0; - dimensions[i + 1] = 0; - } - } - - double topCornerWidth = (dimensions[0] + dimensions[2]) / 2d; - double bottomCornerWidth = (dimensions[4] + dimensions[6]) / 2d; - double leftCornerHeight = (dimensions[1] + dimensions[7]) / 2d; - double rightCornerHeight = (dimensions[3] + dimensions[5]) / 2d; - - // Rescale the corner dimensions if they are bigger than the rectangle - double scale = Math.min(1.0, width / topCornerWidth); - scale = Math.min(scale, width / bottomCornerWidth); - scale = Math.min(scale, height / leftCornerHeight); - scale = Math.min(scale, height / rightCornerHeight); - - this.ulWidth = dimensions[0] * scale; - this.ulHeight = dimensions[1] * scale; - this.urWidth = dimensions[2] * scale; - this.urHeight = dimensions[3] * scale; - this.lrWidth = dimensions[4] * scale; - this.lrHeight = dimensions[5] * scale; - this.llWidth = dimensions[6] * scale; - this.llHeight = dimensions[7] * scale; - } - - @Override - public double getX() { - return x; - } - - @Override - public double getY() { - return y; - } - - @Override - public double getWidth() { - return width; - } - - @Override - public double getHeight() { - return height; - } - - @Override - public boolean isEmpty() { - return (width <= 0d) || (height <= 0d); - } - - @Override - public void setFrame(double x, double y, double w, double h) { - this.x = x; - this.y = y; - this.width = w; - this.height = h; - } - - @Override - public Rectangle2D getBounds2D() { - return new Rectangle2D.Double(x, y, width, height); - } - - @Override - public boolean contains(double x, double y) { - if (isEmpty()) { - return false; - } - - double x0 = getX(); - double y0 = getY(); - double x1 = x0 + getWidth(); - double y1 = y0 + getHeight(); - // Check for trivial rejection - point is outside bounding rectangle - if (x < x0 || y < y0 || x >= x1 || y >= y1) { - return false; - } - - double insideTopX0 = x0 + ulWidth / 2d; - double insideLeftY0 = y0 + ulHeight / 2d; - if (x < insideTopX0 && y < insideLeftY0) { - // In the upper-left corner - return isInsideCorner(x - insideTopX0, y - insideLeftY0, ulWidth / 2d, ulHeight / 2d); - } - - double insideTopX1 = x1 - urWidth / 2d; - double insideRightY0 = y0 + urHeight / 2d; - if (x > insideTopX1 && y < insideRightY0) { - // In the upper-right corner - return isInsideCorner(x - insideTopX1, y - insideRightY0, urWidth / 2d, urHeight / 2d); - } - - double insideBottomX1 = x1 - lrWidth / 2d; - double insideRightY1 = y1 - lrHeight / 2d; - if (x > insideBottomX1 && y > insideRightY1) { - // In the lower-right corner - return isInsideCorner(x - insideBottomX1, y - insideRightY1, lrWidth / 2d, - lrHeight / 2d); - } - - double insideBottomX0 = x0 + llWidth / 2d; - double insideLeftY1 = y1 - llHeight / 2d; - if (x < insideBottomX0 && y > insideLeftY1) { - // In the lower-left corner - return isInsideCorner(x - insideBottomX0, y - insideLeftY1, llWidth / 2d, - llHeight / 2d); - } - - // In the central part of the rectangle - return true; - } - - private boolean isInsideCorner(double x, double y, double width, double height) { - double squareDist = height * height * x * x + width * width * y * y; - return squareDist <= width * width * height * height; - } - - private Zone classify(double coord, double side1, double arcSize1, double side2, - double arcSize2) { - if (coord < side1) { - return Zone.CLOSE_OUTSIDE; - } else if (coord < side1 + arcSize1) { - return Zone.CLOSE_INSIDE; - } else if (coord < side2 - arcSize2) { - return Zone.MIDDLE; - } else if (coord < side2) { - return Zone.FAR_INSIDE; - } else { - return Zone.FAR_OUTSIDE; - } - } - - public boolean intersects(double x, double y, double w, double h) { - if (isEmpty() || w <= 0 || h <= 0) { - return false; - } - double x0 = getX(); - double y0 = getY(); - double x1 = x0 + getWidth(); - double y1 = y0 + getHeight(); - // Check for trivial rejection - bounding rectangles do not intersect - if (x + w <= x0 || x >= x1 || y + h <= y0 || y >= y1) { - return false; - } - - double maxLeftCornerWidth = Math.max(ulWidth, llWidth) / 2d; - double maxRightCornerWidth = Math.max(urWidth, lrWidth) / 2d; - double maxUpperCornerHeight = Math.max(ulHeight, urHeight) / 2d; - double maxLowerCornerHeight = Math.max(llHeight, lrHeight) / 2d; - Zone x0class = classify(x, x0, maxLeftCornerWidth, x1, maxRightCornerWidth); - Zone x1class = classify(x + w, x0, maxLeftCornerWidth, x1, maxRightCornerWidth); - Zone y0class = classify(y, y0, maxUpperCornerHeight, y1, maxLowerCornerHeight); - Zone y1class = classify(y + h, y0, maxUpperCornerHeight, y1, maxLowerCornerHeight); - - // Trivially accept if any point is inside inner rectangle - if (x0class == Zone.MIDDLE || x1class == Zone.MIDDLE || y0class == Zone.MIDDLE || y1class == Zone.MIDDLE) { - return true; - } - // Trivially accept if either edge spans inner rectangle - if ((close.contains(x0class) && far.contains(x1class)) || (close.contains(y0class) && - far.contains(y1class))) { - return true; - } - - // Since neither edge spans the center, then one of the corners - // must be in one of the rounded edges. We detect this case if - // a [xy]0class is 3 or a [xy]1class is 1. One of those two cases - // must be true for each direction. - // We now find a "nearest point" to test for being inside a rounded - // corner. - if (x1class == Zone.CLOSE_INSIDE && y1class == Zone.CLOSE_INSIDE) { - // Potentially in upper-left corner - x = x + w - x0 - ulWidth / 2d; - y = y + h - y0 - ulHeight / 2d; - return x > 0 || y > 0 || isInsideCorner(x, y, ulWidth / 2d, ulHeight / 2d); - } - if (x1class == Zone.CLOSE_INSIDE) { - // Potentially in lower-left corner - x = x + w - x0 - llWidth / 2d; - y = y - y1 + llHeight / 2d; - return x > 0 || y < 0 || isInsideCorner(x, y, llWidth / 2d, llHeight / 2d); - } - if (y1class == Zone.CLOSE_INSIDE) { - //Potentially in the upper-right corner - x = x - x1 + urWidth / 2d; - y = y + h - y0 - urHeight / 2d; - return x < 0 || y > 0 || isInsideCorner(x, y, urWidth / 2d, urHeight / 2d); - } - // Potentially in the lower-right corner - x = x - x1 + lrWidth / 2d; - y = y - y1 + lrHeight / 2d; - return x < 0 || y < 0 || isInsideCorner(x, y, lrWidth / 2d, lrHeight / 2d); - } - - @Override - public boolean contains(double x, double y, double w, double h) { - if (isEmpty() || w <= 0 || h <= 0) { - return false; - } - return (contains(x, y) && - contains(x + w, y) && - contains(x, y + h) && - contains(x + w, y + h)); - } - - @Override - public PathIterator getPathIterator(final AffineTransform at) { - return new PathIterator() { - int index; - - // ArcIterator.btan(Math.PI/2) - public static final double CtrlVal = 0.5522847498307933; - private final double ncv = 1.0 - CtrlVal; - - // Coordinates of control points for Bezier curves approximating the straight lines - // and corners of the rounded rectangle. - private final double[][] ctrlpts = { - {0.0, 0.0, 0.0, ulHeight}, - {0.0, 0.0, 1.0, -llHeight}, - {0.0, 0.0, 1.0, -llHeight * ncv, 0.0, ncv * llWidth, 1.0, 0.0, 0.0, llWidth, - 1.0, 0.0}, - {1.0, -lrWidth, 1.0, 0.0}, - {1.0, -lrWidth * ncv, 1.0, 0.0, 1.0, 0.0, 1.0, -lrHeight * ncv, 1.0, 0.0, 1.0, - -lrHeight}, - {1.0, 0.0, 0.0, urHeight}, - {1.0, 0.0, 0.0, ncv * urHeight, 1.0, -urWidth * ncv, 0.0, 0.0, 1.0, -urWidth, - 0.0, 0.0}, - {0.0, ulWidth, 0.0, 0.0}, - {0.0, ncv * ulWidth, 0.0, 0.0, 0.0, 0.0, 0.0, ncv * ulHeight, 0.0, 0.0, 0.0, - ulHeight}, - {} - }; - private final int[] types = { - SEG_MOVETO, - SEG_LINETO, SEG_CUBICTO, - SEG_LINETO, SEG_CUBICTO, - SEG_LINETO, SEG_CUBICTO, - SEG_LINETO, SEG_CUBICTO, - SEG_CLOSE, - }; - - @Override - public int getWindingRule() { - return WIND_NON_ZERO; - } - - @Override - public boolean isDone() { - return index >= ctrlpts.length; - } - - @Override - public void next() { - index++; - } - - @Override - public int currentSegment(float[] coords) { - if (isDone()) { - throw new NoSuchElementException("roundrect iterator out of bounds"); - } - int nc = 0; - double ctrls[] = ctrlpts[index]; - for (int i = 0; i < ctrls.length; i += 4) { - coords[nc++] = (float) (x + ctrls[i] * width + ctrls[i + 1] / 2d); - coords[nc++] = (float) (y + ctrls[i + 2] * height + ctrls[i + 3] / 2d); - } - if (at != null) { - at.transform(coords, 0, coords, 0, nc / 2); - } - return types[index]; - } - - @Override - public int currentSegment(double[] coords) { - if (isDone()) { - throw new NoSuchElementException("roundrect iterator out of bounds"); - } - int nc = 0; - double ctrls[] = ctrlpts[index]; - for (int i = 0; i < ctrls.length; i += 4) { - coords[nc++] = x + ctrls[i] * width + ctrls[i + 1] / 2d; - coords[nc++] = y + ctrls[i + 2] * height + ctrls[i + 3] / 2d; - } - if (at != null) { - at.transform(coords, 0, coords, 0, nc / 2); - } - return types[index]; - } - }; - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java deleted file mode 100644 index 5b750899392c..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.graphics.Shader.TileMode; - -/** - * Delegate implementing the native methods of android.graphics.Shader - * - * Through the layoutlib_create tool, the original native methods of Shader 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 Shader class. - * - * This also serve as a base class for all Shader delegate classes. - * - * @see DelegateManager - * - */ -public abstract class Shader_Delegate { - - // ---- delegate manager ---- - protected static final DelegateManager<Shader_Delegate> sManager = - new DelegateManager<Shader_Delegate>(Shader_Delegate.class); - - // ---- delegate helper data ---- - - // ---- delegate data ---- - private Matrix_Delegate mLocalMatrix = null; - - // ---- Public Helper methods ---- - - public static Shader_Delegate getDelegate(long nativeShader) { - return sManager.getDelegate(nativeShader); - } - - /** - * Returns the {@link TileMode} matching the given int. - * @param tileMode the tile mode int value - * @return the TileMode enum. - */ - public static TileMode getTileMode(int tileMode) { - for (TileMode tm : TileMode.values()) { - if (tm.nativeInt == tileMode) { - return tm; - } - } - - assert false; - return TileMode.CLAMP; - } - - public abstract java.awt.Paint getJavaPaint(); - public abstract boolean isSupported(); - public abstract String getSupportMessage(); - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static void nativeSafeUnref(long nativeInstance) { - sManager.removeJavaReferenceFor(nativeInstance); - } - - // ---- Private delegate/helper methods ---- - - protected Shader_Delegate(long nativeMatrix) { - mLocalMatrix = Matrix_Delegate.getDelegate(nativeMatrix); - } - - protected java.awt.geom.AffineTransform getLocalMatrix() { - if (mLocalMatrix != null) { - return mLocalMatrix.getAffineTransform(); - } - - return new java.awt.geom.AffineTransform(); - } - -} diff --git a/tools/layoutlib/bridge/src/android/graphics/SumPathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/SumPathEffect_Delegate.java deleted file mode 100644 index 6d2e9b41cc19..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/SumPathEffect_Delegate.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import java.awt.Stroke; - -/** - * Delegate implementing the native methods of android.graphics.SumPathEffect - * - * Through the layoutlib_create tool, the original native methods of SumPathEffect 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 SumPathEffect class. - * - * Because this extends {@link PathEffect_Delegate}, there's no need to use a {@link DelegateManager}, - * as all the Shader classes will be added to the manager owned by {@link PathEffect_Delegate}. - * - * @see PathEffect_Delegate - * - */ -public class SumPathEffect_Delegate extends PathEffect_Delegate { - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - @Override - public Stroke getStroke(Paint_Delegate paint) { - // FIXME - return null; - } - - @Override - public boolean isSupported() { - return false; - } - - @Override - public String getSupportMessage() { - return "Sum Path Effects are not supported in Layout Preview mode."; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static long nativeCreate(long first, long second) { - SumPathEffect_Delegate newDelegate = new SumPathEffect_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java deleted file mode 100644 index 30152bc6b000..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.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; - -/** - * Delegate implementing the native methods of android.graphics.SweepGradient - * - * Through the layoutlib_create tool, the original native methods of SweepGradient 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 SweepGradient class. - * - * Because this extends {@link Shader_Delegate}, there's no need to use a {@link DelegateManager}, - * as all the Shader classes will be added to the manager owned by {@link Shader_Delegate}. - * - * @see Shader_Delegate - * - */ -public class SweepGradient_Delegate extends Gradient_Delegate { - - // ---- delegate data ---- - private java.awt.Paint mJavaPaint; - - // ---- Public Helper methods ---- - - @Override - public java.awt.Paint getJavaPaint() { - return mJavaPaint; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static long nativeCreate1(long matrix, float x, float y, int colors[], float - positions[]) { - SweepGradient_Delegate newDelegate = new SweepGradient_Delegate(matrix, x, y, colors, - positions); - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static long nativeCreate2(long matrix, float x, float y, int color0, int color1) { - return nativeCreate1(matrix, x, y, new int[] { color0, color1 }, - null /*positions*/); - } - - // ---- Private delegate/helper methods ---- - - /** - * A subclass of Shader that draws a sweep gradient around a center point. - * - * @param nativeMatrix reference to the shader's native transformation matrix - * @param cx The x-coordinate of the center - * @param cy The y-coordinate of the center - * @param colors The colors to be distributed between around the center. - * There must be at least 2 colors in the array. - * @param positions May be NULL. The relative position of - * each corresponding color in the colors array, beginning - * with 0 and ending with 1.0. If the values are not - * monotonic, the drawing may produce unexpected results. - * If positions is NULL, then the colors are automatically - * spaced evenly. - */ - private SweepGradient_Delegate(long nativeMatrix, float cx, float cy, - int colors[], float positions[]) { - super(nativeMatrix, colors, positions); - mJavaPaint = new SweepGradientPaint(cx, cy, mColors, mPositions); - } - - private class SweepGradientPaint extends GradientPaint { - - private final float mCx; - private final float mCy; - - public SweepGradientPaint(float cx, float cy, int[] colors, - float[] positions) { - super(colors, positions, null /*tileMode*/); - mCx = cx; - mCy = cy; - } - - @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) { - precomputeGradientColors(); - - java.awt.geom.AffineTransform canvasMatrix; - try { - canvasMatrix = xform.createInverse(); - } catch (java.awt.geom.NoninvertibleTransformException e) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE, - "Unable to inverse matrix in SweepGradient", e, null /*data*/); - canvasMatrix = new java.awt.geom.AffineTransform(); - } - - java.awt.geom.AffineTransform localMatrix = getLocalMatrix(); - try { - localMatrix = localMatrix.createInverse(); - } catch (java.awt.geom.NoninvertibleTransformException e) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE, - "Unable to inverse matrix in SweepGradient", e, null /*data*/); - localMatrix = new java.awt.geom.AffineTransform(); - } - - return new SweepGradientPaintContext(canvasMatrix, localMatrix, colorModel); - } - - private class SweepGradientPaintContext implements java.awt.PaintContext { - - private final java.awt.geom.AffineTransform mCanvasMatrix; - private final java.awt.geom.AffineTransform mLocalMatrix; - private final java.awt.image.ColorModel mColorModel; - - public SweepGradientPaintContext( - java.awt.geom.AffineTransform canvasMatrix, - java.awt.geom.AffineTransform localMatrix, - java.awt.image.ColorModel colorModel) { - mCanvasMatrix = canvasMatrix; - mLocalMatrix = localMatrix; - mColorModel = colorModel; - } - - @Override - public void dispose() { - } - - @Override - public java.awt.image.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( - mColorModel, mColorModel.createCompatibleWritableRaster(w, h), - mColorModel.isAlphaPremultiplied(), null); - - int[] data = new int[w*h]; - - // compute angle from each point to the center, and figure out the distance from - // it. - int index = 0; - float[] pt1 = new float[2]; - float[] pt2 = new float[2]; - for (int iy = 0 ; iy < h ; iy++) { - for (int ix = 0 ; ix < w ; ix++) { - // handle the canvas transform - pt1[0] = x + ix; - pt1[1] = y + iy; - mCanvasMatrix.transform(pt1, 0, pt2, 0, 1); - - // handle the local matrix - pt1[0] = pt2[0] - mCx; - pt1[1] = pt2[1] - mCy; - mLocalMatrix.transform(pt1, 0, pt2, 0, 1); - - float dx = pt2[0]; - float dy = pt2[1]; - - float angle; - if (dx == 0) { - angle = (float) (dy < 0 ? 3 * Math.PI / 2 : Math.PI / 2); - } else if (dy == 0) { - angle = (float) (dx < 0 ? Math.PI : 0); - } else { - angle = (float) Math.atan(dy / dx); - if (dx > 0) { - if (dy < 0) { - angle += Math.PI * 2; - } - } else { - angle += Math.PI; - } - } - - // convert to 0-1. value and get color - data[index++] = getGradientColor((float) (angle / (2 * Math.PI))); - } - } - - image.setRGB(0 /*startX*/, 0 /*startY*/, w, h, data, 0 /*offset*/, w /*scansize*/); - - return image.getRaster(); - } - - } - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Accessor.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Accessor.java deleted file mode 100644 index ce669cba9c47..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Accessor.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import android.annotation.NonNull; - -/** - * Class allowing access to package-protected methods/fields. - */ -public class Typeface_Accessor { - public static boolean isSystemFont(@NonNull String fontName) { - return Typeface.sSystemFontMap.containsKey(fontName); - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java deleted file mode 100644 index a04a32425fde..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import com.android.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.FontFamily_Delegate.FontVariant; -import android.graphics.fonts.FontVariationAxis; -import android.text.FontConfig; - -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; - -/** - * Delegate implementing the native methods of android.graphics.Typeface - * - * Through the layoutlib_create tool, the original native methods of Typeface have been replaced - * by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original Typeface class. - * - * @see DelegateManager - * - */ -public final class Typeface_Delegate { - - public static final String SYSTEM_FONTS = "/system/fonts/"; - - // ---- delegate manager ---- - private static final DelegateManager<Typeface_Delegate> sManager = - new DelegateManager<Typeface_Delegate>(Typeface_Delegate.class); - - - // ---- delegate data ---- - - @NonNull - private final FontFamily_Delegate[] mFontFamilies; // the reference to FontFamily_Delegate. - /** @see Font#getStyle() */ - private final int mStyle; - private final int mWeight; - - private static long sDefaultTypeface; - - - // ---- Public Helper methods ---- - - public static Typeface_Delegate getDelegate(long nativeTypeface) { - return sManager.getDelegate(nativeTypeface); - } - - /** - * Return a list of fonts that match the style and variant. The list is ordered according to - * preference of fonts. - * - * The list may contain null when the font failed to load. If null is reached when trying to - * render with this list of fonts, then a warning should be logged letting the user know that - * some font failed to load. - * - * @param variant The variant preferred. Can only be {@link FontVariant#COMPACT} or - * {@link FontVariant#ELEGANT} - */ - @NonNull - public List<Font> getFonts(FontVariant variant) { - assert variant != FontVariant.NONE; - - // Calculate the required weight based on style and weight of this typeface. - int weight = mWeight + 50 + - ((mStyle & Font.BOLD) == 0 ? 0 : FontFamily_Delegate.BOLD_FONT_WEIGHT_DELTA); - if (weight > 1000) { - weight = 1000; - } else if (weight < 100) { - weight = 100; - } - final boolean isItalic = (mStyle & Font.ITALIC) != 0; - List<Font> fonts = new ArrayList<Font>(mFontFamilies.length); - for (int i = 0; i < mFontFamilies.length; i++) { - FontFamily_Delegate ffd = mFontFamilies[i]; - if (ffd != null && ffd.isValid()) { - Font font = ffd.getFont(weight, isItalic); - if (font != null) { - FontVariant ffdVariant = ffd.getVariant(); - if (ffdVariant == FontVariant.NONE) { - fonts.add(font); - continue; - } - // We cannot open each font and get locales supported, etc to match the fonts. - // As a workaround, we hardcode certain assumptions like Elegant and Compact - // always appear in pairs. - assert i < mFontFamilies.length - 1; - FontFamily_Delegate ffd2 = mFontFamilies[++i]; - assert ffd2 != null; - FontVariant ffd2Variant = ffd2.getVariant(); - Font font2 = ffd2.getFont(weight, isItalic); - assert ffd2Variant != FontVariant.NONE && ffd2Variant != ffdVariant - && font2 != null; - // Add the font with the matching variant to the list. - if (variant == ffd.getVariant()) { - fonts.add(font); - } else { - fonts.add(font2); - } - } else { - // The FontFamily is valid but doesn't contain any matching font. This means - // that the font failed to load. We add null to the list of fonts. Don't throw - // the warning just yet. If this is a non-english font, we don't want to warn - // users who are trying to render only english text. - fonts.add(null); - } - } - } - return fonts; - } - - /** - * Clear the default typefaces when disposing bridge. - */ - public static void resetDefaults() { - // Sometimes this is called before the Bridge is initialized. In that case, we don't want to - // initialize Typeface because the SDK fonts location hasn't been set. - if (FontFamily_Delegate.getFontLocation() != null) { - Typeface.sDefaults = null; - } - } - - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static synchronized long nativeCreateFromTypeface(long native_instance, int style) { - Typeface_Delegate delegate = sManager.getDelegate(native_instance); - if (delegate == null) { - delegate = sManager.getDelegate(sDefaultTypeface); - } - if (delegate == null) { - return 0; - } - - return sManager.addNewDelegate(new Typeface_Delegate(delegate.mFontFamilies, style, - delegate.mWeight)); - } - - @LayoutlibDelegate - /*package*/ static long nativeCreateFromTypefaceWithExactStyle(long native_instance, - int weight, boolean italic) { - Typeface_Delegate delegate = sManager.getDelegate(native_instance); - if (delegate == null) { - delegate = sManager.getDelegate(sDefaultTypeface); - } - if (delegate == null) { - return 0; - } - - int style = weight >= 600 ? (italic ? Typeface.BOLD_ITALIC : Typeface.BOLD) : - (italic ? Typeface.ITALIC : Typeface.NORMAL); - return sManager.addNewDelegate(new Typeface_Delegate(delegate.mFontFamilies, style, weight)); - } - - @LayoutlibDelegate - /*package*/ static synchronized long nativeCreateFromTypefaceWithVariation(long native_instance, - List<FontVariationAxis> axes) { - long newInstance = nativeCreateFromTypeface(native_instance, 0); - - if (newInstance != 0) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "nativeCreateFromTypefaceWithVariation is not supported", null, null); - } - return newInstance; - } - - @LayoutlibDelegate - /*package*/ static synchronized int[] nativeGetSupportedAxes(long native_instance) { - // nativeCreateFromTypefaceWithVariation is not supported so we do not keep the axes - return null; - } - - @LayoutlibDelegate - /*package*/ static long nativeCreateWeightAlias(long native_instance, int weight) { - Typeface_Delegate delegate = sManager.getDelegate(native_instance); - if (delegate == null) { - delegate = sManager.getDelegate(sDefaultTypeface); - } - if (delegate == null) { - return 0; - } - Typeface_Delegate weightAlias = - new Typeface_Delegate(delegate.mFontFamilies, delegate.mStyle, weight); - return sManager.addNewDelegate(weightAlias); - } - - @LayoutlibDelegate - /*package*/ static synchronized long nativeCreateFromArray(long[] familyArray, int weight, - int italic) { - FontFamily_Delegate[] fontFamilies = new FontFamily_Delegate[familyArray.length]; - for (int i = 0; i < familyArray.length; i++) { - fontFamilies[i] = FontFamily_Delegate.getDelegate(familyArray[i]); - } - if (weight == Typeface.RESOLVE_BY_FONT_TABLE) { - weight = 400; - } - if (italic == Typeface.RESOLVE_BY_FONT_TABLE) { - italic = 0; - } - int style = weight >= 600 ? (italic == 1 ? Typeface.BOLD_ITALIC : Typeface.BOLD) : - (italic == 1 ? Typeface.ITALIC : Typeface.NORMAL); - Typeface_Delegate delegate = new Typeface_Delegate(fontFamilies, style, weight); - return sManager.addNewDelegate(delegate); - } - - @LayoutlibDelegate - /*package*/ static void nativeUnref(long native_instance) { - sManager.removeJavaReferenceFor(native_instance); - } - - @LayoutlibDelegate - /*package*/ static int nativeGetStyle(long native_instance) { - Typeface_Delegate delegate = sManager.getDelegate(native_instance); - if (delegate == null) { - return 0; - } - - return delegate.mStyle; - } - - @LayoutlibDelegate - /*package*/ static void nativeSetDefault(long native_instance) { - sDefaultTypeface = native_instance; - } - - @LayoutlibDelegate - /*package*/ static int nativeGetWeight(long native_instance) { - Typeface_Delegate delegate = sManager.getDelegate(native_instance); - if (delegate == null) { - return 0; - } - return delegate.mWeight; - } - - @LayoutlibDelegate - /*package*/ static File getSystemFontConfigLocation() { - return new File(getFontLocation()); - } - - @LayoutlibDelegate - /*package*/ static FontFamily makeFamilyFromParsed(FontConfig.Family family, - Map<String, ByteBuffer> bufferForPath) { - FontFamily fontFamily = new FontFamily(family.getLanguage(), family.getVariant()); - for (FontConfig.Font font : family.getFonts()) { - String fullPathName = "/system/fonts/" + font.getFontName(); - FontFamily_Delegate.addFont(fontFamily.mBuilderPtr, fullPathName, - font.getWeight(), font.isItalic()); - } - fontFamily.freeze(); - return fontFamily; - } - - // ---- Private delegate/helper methods ---- - - public Typeface_Delegate(@NonNull FontFamily_Delegate[] fontFamilies, int style, int weight) { - mFontFamilies = fontFamilies; - mStyle = style; - mWeight = weight; - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_Delegate.java deleted file mode 100644 index ad2c5647eef2..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_Delegate.java +++ /dev/null @@ -1,298 +0,0 @@ -/* - * 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 android.graphics.drawable; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.internal.view.animation.NativeInterpolatorFactoryHelper_Delegate; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.animation.Animator; -import android.animation.AnimatorSet; -import android.animation.ObjectAnimator; -import android.animation.PropertyValuesHolder; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.graphics.drawable.AnimatedVectorDrawable.VectorDrawableAnimatorRT; -import android.graphics.drawable.VectorDrawable_Delegate.VFullPath_Delegate; -import android.graphics.drawable.VectorDrawable_Delegate.VGroup_Delegate; -import android.graphics.drawable.VectorDrawable_Delegate.VNativeObject; -import android.graphics.drawable.VectorDrawable_Delegate.VPathRenderer_Delegate; - -import java.util.ArrayList; -import java.util.function.Consumer; - -/** - * Delegate used to provide new implementation of a select few methods of {@link - * AnimatedVectorDrawable} - * <p> - * Through the layoutlib_create tool, the original methods of AnimatedVectorDrawable have been - * replaced by calls to methods of the same name in this delegate class. - */ -@SuppressWarnings("unused") -public class AnimatedVectorDrawable_Delegate { - private static DelegateManager<AnimatorSetHolder> sAnimatorSets = new - DelegateManager<>(AnimatorSetHolder.class); - private static DelegateManager<PropertySetter> sHolders = new - DelegateManager<>(PropertySetter.class); - - - @LayoutlibDelegate - /*package*/ static long nCreateAnimatorSet() { - return sAnimatorSets.addNewDelegate(new AnimatorSetHolder()); - } - - @LayoutlibDelegate - /*package*/ static void nSetVectorDrawableTarget(long animatorPtr, long vectorDrawablePtr) { - // TODO: implement - } - @LayoutlibDelegate - /*package*/ static void nAddAnimator(long setPtr, long propertyValuesHolder, - long nativeInterpolator, long startDelay, long duration, int repeatCount, - int repeatMode) { - PropertySetter holder = sHolders.getDelegate(propertyValuesHolder); - if (holder == null || holder.getValues() == null) { - return; - } - - ObjectAnimator animator = new ObjectAnimator(); - animator.setValues(holder.getValues()); - animator.setInterpolator( - NativeInterpolatorFactoryHelper_Delegate.getDelegate(nativeInterpolator)); - animator.setStartDelay(startDelay); - animator.setDuration(duration); - animator.setRepeatCount(repeatCount); - animator.setRepeatMode(repeatMode); - animator.setTarget(holder); - animator.setPropertyName(holder.getValues().getPropertyName()); - - AnimatorSetHolder set = sAnimatorSets.getDelegate(setPtr); - assert set != null; - set.addAnimator(animator); - } - - @LayoutlibDelegate - /*package*/ static long nCreateGroupPropertyHolder(long nativePtr, int propertyId, - float startValue, float endValue) { - VGroup_Delegate group = VNativeObject.getDelegate(nativePtr); - Consumer<Float> setter = group.getPropertySetter(propertyId); - - return sHolders.addNewDelegate(FloatPropertySetter.of(setter, startValue, - endValue)); - } - - @LayoutlibDelegate - /*package*/ static long nCreatePathDataPropertyHolder(long nativePtr, long startValuePtr, - long endValuePtr) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, "AnimatedVectorDrawable path " + - "animations are not supported.", null, null); - return 0; - } - - @LayoutlibDelegate - /*package*/ static long nCreatePathColorPropertyHolder(long nativePtr, int propertyId, - int startValue, int endValue) { - VFullPath_Delegate path = VNativeObject.getDelegate(nativePtr); - Consumer<Integer> setter = path.getIntPropertySetter(propertyId); - - return sHolders.addNewDelegate(IntPropertySetter.of(setter, startValue, - endValue)); - } - - @LayoutlibDelegate - /*package*/ static long nCreatePathPropertyHolder(long nativePtr, int propertyId, - float startValue, float endValue) { - VFullPath_Delegate path = VNativeObject.getDelegate(nativePtr); - Consumer<Float> setter = path.getFloatPropertySetter(propertyId); - - return sHolders.addNewDelegate(FloatPropertySetter.of(setter, startValue, - endValue)); - } - - @LayoutlibDelegate - /*package*/ static long nCreateRootAlphaPropertyHolder(long nativePtr, float startValue, - float endValue) { - VPathRenderer_Delegate renderer = VNativeObject.getDelegate(nativePtr); - - return sHolders.addNewDelegate(FloatPropertySetter.of(renderer::setRootAlpha, - startValue, - endValue)); - } - - @LayoutlibDelegate - /*package*/ static void nSetPropertyHolderData(long nativePtr, float[] data, int length) { - PropertySetter setter = sHolders.getDelegate(nativePtr); - assert setter != null; - - setter.setValues(data); - } - - @LayoutlibDelegate - /*package*/ static void nSetPropertyHolderData(long nativePtr, int[] data, int length) { - PropertySetter setter = sHolders.getDelegate(nativePtr); - assert setter != null; - - setter.setValues(data); - } - - @LayoutlibDelegate - /*package*/ static void nStart(long animatorSetPtr, VectorDrawableAnimatorRT set, int id) { - AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr); - assert animatorSet != null; - - animatorSet.start(); - } - - @LayoutlibDelegate - /*package*/ static void nReverse(long animatorSetPtr, VectorDrawableAnimatorRT set, int id) { - AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr); - assert animatorSet != null; - - animatorSet.reverse(); - } - - @LayoutlibDelegate - /*package*/ static void nEnd(long animatorSetPtr) { - AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr); - assert animatorSet != null; - - animatorSet.end(); - } - - @LayoutlibDelegate - /*package*/ static void nReset(long animatorSetPtr) { - AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr); - assert animatorSet != null; - - animatorSet.end(); - animatorSet.start(); - } - - private static class AnimatorSetHolder { - private ArrayList<Animator> mAnimators = new ArrayList<>(); - private AnimatorSet mAnimatorSet = null; - - private void addAnimator(@NonNull Animator animator) { - mAnimators.add(animator); - } - - private void ensureAnimatorSet() { - if (mAnimatorSet == null) { - mAnimatorSet = new AnimatorSet(); - mAnimatorSet.playTogether(mAnimators); - } - } - - private void start() { - ensureAnimatorSet(); - - mAnimatorSet.start(); - } - - private void end() { - mAnimatorSet.end(); - } - - private void reset() { - end(); - start(); - } - - private void reverse() { - mAnimatorSet.reverse(); - } - } - - /** - * Class that allows setting a value and holds the range of values for the given property. - * - * @param <T> the type of the property - */ - private static class PropertySetter<T> { - final Consumer<T> mValueSetter; - private PropertyValuesHolder mValues; - - private PropertySetter(@NonNull Consumer<T> valueSetter) { - mValueSetter = valueSetter; - } - - /** - * Method to set an {@link Integer} value for this property. The default implementation of - * this method doesn't do anything. This method is accessed via reflection by the - * PropertyValuesHolder. - */ - public void setIntValue(Integer value) { - } - - /** - * Method to set an {@link Integer} value for this property. The default implementation of - * this method doesn't do anything. This method is accessed via reflection by the - * PropertyValuesHolder. - */ - public void setFloatValue(Float value) { - } - - void setValues(float... values) { - mValues = PropertyValuesHolder.ofFloat("floatValue", values); - } - - @Nullable - PropertyValuesHolder getValues() { - return mValues; - } - - void setValues(int... values) { - mValues = PropertyValuesHolder.ofInt("intValue", values); - } - } - - private static class IntPropertySetter extends PropertySetter<Integer> { - private IntPropertySetter(Consumer<Integer> valueSetter) { - super(valueSetter); - } - - private static PropertySetter of(Consumer<Integer> valueSetter, int... values) { - PropertySetter setter = new IntPropertySetter(valueSetter); - setter.setValues(values); - - return setter; - } - - public void setIntValue(Integer value) { - mValueSetter.accept(value); - } - } - - private static class FloatPropertySetter extends PropertySetter<Float> { - private FloatPropertySetter(Consumer<Float> valueSetter) { - super(valueSetter); - } - - private static PropertySetter of(Consumer<Float> valueSetter, float... values) { - PropertySetter setter = new FloatPropertySetter(valueSetter); - setter.setValues(values); - - return setter; - } - - public void setFloatValue(Float value) { - mValueSetter.accept(value); - } - - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_VectorDrawableAnimatorRT_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_VectorDrawableAnimatorRT_Delegate.java deleted file mode 100644 index fc848d9af956..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_VectorDrawableAnimatorRT_Delegate.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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 android.graphics.drawable; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.graphics.Canvas; -import android.graphics.drawable.AnimatedVectorDrawable.VectorDrawableAnimatorRT; - -public class AnimatedVectorDrawable_VectorDrawableAnimatorRT_Delegate { - @LayoutlibDelegate - /*package*/ static boolean useLastSeenTarget(VectorDrawableAnimatorRT thisDrawableAnimator) { - return true; - } - - @LayoutlibDelegate - /*package*/ static void onDraw(VectorDrawableAnimatorRT thisDrawableAnimator, Canvas canvas) { - // Do not attempt to record as we are not using a DisplayListCanvas - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/drawable/GradientDrawable_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/drawable/GradientDrawable_Delegate.java deleted file mode 100644 index a3ad2aac7d3d..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/drawable/GradientDrawable_Delegate.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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.graphics.drawable; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.graphics.Path; -import android.graphics.drawable.GradientDrawable.GradientState; - -import java.lang.reflect.Field; - -/** - * Delegate implementing the native methods of {@link GradientDrawable} - * - * Through the layoutlib_create tool, the original native methods of GradientDrawable have been - * replaced by calls to methods of the same name in this delegate class. - */ -public class GradientDrawable_Delegate { - - /** - * The ring can be built either by drawing full circles, or by drawing arcs in case the - * circle isn't complete. LayoutLib cannot handle drawing full circles (requires path - * subtraction). So, if we need to draw full circles, we switch to drawing 99% circle. - */ - @LayoutlibDelegate - /*package*/ static Path buildRing(GradientDrawable thisDrawable, GradientState st) { - boolean useLevel = st.mUseLevelForShape; - int level = thisDrawable.getLevel(); - // 10000 is the max level. See android.graphics.drawable.Drawable#getLevel() - float sweep = useLevel ? (360.0f * level / 10000.0f) : 360f; - Field mLevel = null; - if (sweep >= 360 || sweep <= -360) { - st.mUseLevelForShape = true; - // Use reflection to set the value of the field to prevent setting the drawable to - // dirty again. - try { - mLevel = Drawable.class.getDeclaredField("mLevel"); - mLevel.setAccessible(true); - mLevel.setInt(thisDrawable, 9999); // set to one less than max. - } catch (NoSuchFieldException e) { - // The field has been removed in a recent framework change. Fall back to old - // buggy behaviour. - } catch (IllegalAccessException e) { - // We've already set the field to be accessible. - assert false; - } - } - Path path = thisDrawable.buildRing_Original(st); - st.mUseLevelForShape = useLevel; - if (mLevel != null) { - try { - mLevel.setInt(thisDrawable, level); - } catch (IllegalAccessException e) { - assert false; - } - } - return path; - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java deleted file mode 100644 index 616784c10aae..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java +++ /dev/null @@ -1,1262 +0,0 @@ -/* - * 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 android.graphics.drawable; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.annotation.NonNull; -import android.content.res.Resources; -import android.content.res.Resources.Theme; -import android.content.res.TypedArray; -import android.graphics.BaseCanvas_Delegate; -import android.graphics.Canvas_Delegate; -import android.graphics.Color; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.Paint.Cap; -import android.graphics.Paint.Join; -import android.graphics.Paint_Delegate; -import android.graphics.Path; -import android.graphics.PathMeasure; -import android.graphics.Path_Delegate; -import android.graphics.Rect; -import android.graphics.Region.Op; -import android.util.ArrayMap; -import android.util.AttributeSet; -import android.util.Log; -import android.util.MathUtils; -import android.util.PathParser_Delegate; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.FloatBuffer; -import java.util.ArrayList; -import java.util.function.Consumer; - -import static android.graphics.Canvas.CLIP_SAVE_FLAG; -import static android.graphics.Canvas.MATRIX_SAVE_FLAG; -import static android.graphics.Paint.Cap.BUTT; -import static android.graphics.Paint.Cap.ROUND; -import static android.graphics.Paint.Cap.SQUARE; -import static android.graphics.Paint.Join.BEVEL; -import static android.graphics.Paint.Join.MITER; -import static android.graphics.Paint.Style; - -/** - * Delegate used to provide new implementation of a select few methods of {@link VectorDrawable} - * <p> - * Through the layoutlib_create tool, the original methods of VectorDrawable have been replaced by - * calls to methods of the same name in this delegate class. - */ -@SuppressWarnings("unused") -public class VectorDrawable_Delegate { - private static final String LOGTAG = VectorDrawable_Delegate.class.getSimpleName(); - private static final boolean DBG_VECTOR_DRAWABLE = false; - - private static final DelegateManager<VNativeObject> sPathManager = - new DelegateManager<>(VNativeObject.class); - - private static long addNativeObject(VNativeObject object) { - long ptr = sPathManager.addNewDelegate(object); - object.setNativePtr(ptr); - - return ptr; - } - - /** - * Obtains styled attributes from the theme, if available, or unstyled resources if the theme is - * null. - */ - private static TypedArray obtainAttributes( - Resources res, Theme theme, AttributeSet set, int[] attrs) { - if (theme == null) { - return res.obtainAttributes(set, attrs); - } - return theme.obtainStyledAttributes(set, attrs, 0, 0); - } - - private static int applyAlpha(int color, float alpha) { - int alphaBytes = Color.alpha(color); - color &= 0x00FFFFFF; - color |= ((int) (alphaBytes * alpha)) << 24; - return color; - } - - @LayoutlibDelegate - static long nCreateTree(long rootGroupPtr) { - return addNativeObject(new VPathRenderer_Delegate(rootGroupPtr)); - } - - @LayoutlibDelegate - static long nCreateTreeFromCopy(long rendererToCopyPtr, long rootGroupPtr) { - VPathRenderer_Delegate rendererToCopy = VNativeObject.getDelegate(rendererToCopyPtr); - return addNativeObject(new VPathRenderer_Delegate(rendererToCopy, - rootGroupPtr)); - } - - @LayoutlibDelegate - static void nSetRendererViewportSize(long rendererPtr, float viewportWidth, - float viewportHeight) { - VPathRenderer_Delegate nativePathRenderer = VNativeObject.getDelegate(rendererPtr); - nativePathRenderer.mViewportWidth = viewportWidth; - nativePathRenderer.mViewportHeight = viewportHeight; - } - - @LayoutlibDelegate - static boolean nSetRootAlpha(long rendererPtr, float alpha) { - VPathRenderer_Delegate nativePathRenderer = VNativeObject.getDelegate(rendererPtr); - nativePathRenderer.setRootAlpha(alpha); - - return true; - } - - @LayoutlibDelegate - static float nGetRootAlpha(long rendererPtr) { - VPathRenderer_Delegate nativePathRenderer = VNativeObject.getDelegate(rendererPtr); - - return nativePathRenderer.getRootAlpha(); - } - - @LayoutlibDelegate - static void nSetAllowCaching(long rendererPtr, boolean allowCaching) { - // ignored - } - - @LayoutlibDelegate - static int nDraw(long rendererPtr, long canvasWrapperPtr, - long colorFilterPtr, Rect bounds, boolean needsMirroring, boolean canReuseCache) { - VPathRenderer_Delegate nativePathRenderer = VNativeObject.getDelegate(rendererPtr); - - Canvas_Delegate.nSave(canvasWrapperPtr, MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG); - Canvas_Delegate.nTranslate(canvasWrapperPtr, bounds.left, bounds.top); - - if (needsMirroring) { - Canvas_Delegate.nTranslate(canvasWrapperPtr, bounds.width(), 0); - Canvas_Delegate.nScale(canvasWrapperPtr, -1.0f, 1.0f); - } - - // At this point, canvas has been translated to the right position. - // And we use this bound for the destination rect for the drawBitmap, so - // we offset to (0, 0); - bounds.offsetTo(0, 0); - nativePathRenderer.draw(canvasWrapperPtr, colorFilterPtr, bounds.width(), bounds.height()); - - Canvas_Delegate.nRestore(canvasWrapperPtr); - - return bounds.width() * bounds.height(); - } - - @LayoutlibDelegate - static long nCreateFullPath() { - return addNativeObject(new VFullPath_Delegate()); - } - - @LayoutlibDelegate - static long nCreateFullPath(long nativeFullPathPtr) { - VFullPath_Delegate original = VNativeObject.getDelegate(nativeFullPathPtr); - return addNativeObject(new VFullPath_Delegate(original)); - } - - @LayoutlibDelegate - static boolean nGetFullPathProperties(long pathPtr, byte[] propertiesData, - int length) { - VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr); - - ByteBuffer properties = ByteBuffer.wrap(propertiesData); - properties.order(ByteOrder.nativeOrder()); - - properties.putFloat(VFullPath_Delegate.STROKE_WIDTH_INDEX * 4, path.getStrokeWidth()); - properties.putInt(VFullPath_Delegate.STROKE_COLOR_INDEX * 4, path.getStrokeColor()); - properties.putFloat(VFullPath_Delegate.STROKE_ALPHA_INDEX * 4, path.getStrokeAlpha()); - properties.putInt(VFullPath_Delegate.FILL_COLOR_INDEX * 4, path.getFillColor()); - properties.putFloat(VFullPath_Delegate.FILL_ALPHA_INDEX * 4, path.getStrokeAlpha()); - properties.putFloat(VFullPath_Delegate.TRIM_PATH_START_INDEX * 4, path.getTrimPathStart()); - properties.putFloat(VFullPath_Delegate.TRIM_PATH_END_INDEX * 4, path.getTrimPathEnd()); - properties.putFloat(VFullPath_Delegate.TRIM_PATH_OFFSET_INDEX * 4, - path.getTrimPathOffset()); - properties.putInt(VFullPath_Delegate.STROKE_LINE_CAP_INDEX * 4, path.getStrokeLineCap()); - properties.putInt(VFullPath_Delegate.STROKE_LINE_JOIN_INDEX * 4, path.getStrokeLineJoin()); - properties.putFloat(VFullPath_Delegate.STROKE_MITER_LIMIT_INDEX * 4, - path.getStrokeMiterlimit()); - properties.putInt(VFullPath_Delegate.FILL_TYPE_INDEX * 4, path.getFillType()); - - return true; - } - - @LayoutlibDelegate - static void nUpdateFullPathProperties(long pathPtr, float strokeWidth, - int strokeColor, float strokeAlpha, int fillColor, float fillAlpha, float trimPathStart, - float trimPathEnd, float trimPathOffset, float strokeMiterLimit, int strokeLineCap, - int strokeLineJoin, int fillType) { - VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr); - - path.setStrokeWidth(strokeWidth); - path.setStrokeColor(strokeColor); - path.setStrokeAlpha(strokeAlpha); - path.setFillColor(fillColor); - path.setFillAlpha(fillAlpha); - path.setTrimPathStart(trimPathStart); - path.setTrimPathEnd(trimPathEnd); - path.setTrimPathOffset(trimPathOffset); - path.setStrokeMiterlimit(strokeMiterLimit); - path.setStrokeLineCap(strokeLineCap); - path.setStrokeLineJoin(strokeLineJoin); - path.setFillType(fillType); - } - - @LayoutlibDelegate - static void nUpdateFullPathFillGradient(long pathPtr, long fillGradientPtr) { - VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr); - - path.setFillGradient(fillGradientPtr); - } - - @LayoutlibDelegate - static void nUpdateFullPathStrokeGradient(long pathPtr, long strokeGradientPtr) { - VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr); - - path.setStrokeGradient(strokeGradientPtr); - } - - @LayoutlibDelegate - static long nCreateClipPath() { - return addNativeObject(new VClipPath_Delegate()); - } - - @LayoutlibDelegate - static long nCreateClipPath(long clipPathPtr) { - VClipPath_Delegate original = VNativeObject.getDelegate(clipPathPtr); - return addNativeObject(new VClipPath_Delegate(original)); - } - - @LayoutlibDelegate - static long nCreateGroup() { - return addNativeObject(new VGroup_Delegate()); - } - - @LayoutlibDelegate - static long nCreateGroup(long groupPtr) { - VGroup_Delegate original = VNativeObject.getDelegate(groupPtr); - return addNativeObject(new VGroup_Delegate(original, new ArrayMap<>())); - } - - @LayoutlibDelegate - static void nSetName(long nodePtr, String name) { - VNativeObject group = VNativeObject.getDelegate(nodePtr); - group.setName(name); - } - - @LayoutlibDelegate - static boolean nGetGroupProperties(long groupPtr, float[] propertiesData, - int length) { - VGroup_Delegate group = VNativeObject.getDelegate(groupPtr); - - FloatBuffer properties = FloatBuffer.wrap(propertiesData); - - properties.put(VGroup_Delegate.ROTATE_INDEX, group.getRotation()); - properties.put(VGroup_Delegate.PIVOT_X_INDEX, group.getPivotX()); - properties.put(VGroup_Delegate.PIVOT_Y_INDEX, group.getPivotY()); - properties.put(VGroup_Delegate.SCALE_X_INDEX, group.getScaleX()); - properties.put(VGroup_Delegate.SCALE_Y_INDEX, group.getScaleY()); - properties.put(VGroup_Delegate.TRANSLATE_X_INDEX, group.getTranslateX()); - properties.put(VGroup_Delegate.TRANSLATE_Y_INDEX, group.getTranslateY()); - - return true; - } - @LayoutlibDelegate - static void nUpdateGroupProperties(long groupPtr, float rotate, float pivotX, - float pivotY, float scaleX, float scaleY, float translateX, float translateY) { - VGroup_Delegate group = VNativeObject.getDelegate(groupPtr); - - group.setRotation(rotate); - group.setPivotX(pivotX); - group.setPivotY(pivotY); - group.setScaleX(scaleX); - group.setScaleY(scaleY); - group.setTranslateX(translateX); - group.setTranslateY(translateY); - } - - @LayoutlibDelegate - static void nAddChild(long groupPtr, long nodePtr) { - VGroup_Delegate group = VNativeObject.getDelegate(groupPtr); - group.mChildren.add(VNativeObject.getDelegate(nodePtr)); - } - - @LayoutlibDelegate - static void nSetPathString(long pathPtr, String pathString, int length) { - VPath_Delegate path = VNativeObject.getDelegate(pathPtr); - path.setPathData(PathParser_Delegate.createNodesFromPathData(pathString)); - } - - /** - * The setters and getters below for paths and groups are here temporarily, and will be removed - * once the animation in AVD is replaced with RenderNodeAnimator, in which case the animation - * will modify these properties in native. By then no JNI hopping would be necessary for VD - * during animation, and these setters and getters will be obsolete. - */ - // Setters and getters during animation. - @LayoutlibDelegate - static float nGetRotation(long groupPtr) { - VGroup_Delegate group = VNativeObject.getDelegate(groupPtr); - return group.getRotation(); - } - - @LayoutlibDelegate - static void nSetRotation(long groupPtr, float rotation) { - VGroup_Delegate group = VNativeObject.getDelegate(groupPtr); - group.setRotation(rotation); - } - - @LayoutlibDelegate - static float nGetPivotX(long groupPtr) { - VGroup_Delegate group = VNativeObject.getDelegate(groupPtr); - return group.getPivotX(); - } - - @LayoutlibDelegate - static void nSetPivotX(long groupPtr, float pivotX) { - VGroup_Delegate group = VNativeObject.getDelegate(groupPtr); - group.setPivotX(pivotX); - } - - @LayoutlibDelegate - static float nGetPivotY(long groupPtr) { - VGroup_Delegate group = VNativeObject.getDelegate(groupPtr); - return group.getPivotY(); - } - - @LayoutlibDelegate - static void nSetPivotY(long groupPtr, float pivotY) { - VGroup_Delegate group = VNativeObject.getDelegate(groupPtr); - group.setPivotY(pivotY); - } - - @LayoutlibDelegate - static float nGetScaleX(long groupPtr) { - VGroup_Delegate group = VNativeObject.getDelegate(groupPtr); - return group.getScaleX(); - } - - @LayoutlibDelegate - static void nSetScaleX(long groupPtr, float scaleX) { - VGroup_Delegate group = VNativeObject.getDelegate(groupPtr); - group.setScaleX(scaleX); - } - - @LayoutlibDelegate - static float nGetScaleY(long groupPtr) { - VGroup_Delegate group = VNativeObject.getDelegate(groupPtr); - return group.getScaleY(); - } - - @LayoutlibDelegate - static void nSetScaleY(long groupPtr, float scaleY) { - VGroup_Delegate group = VNativeObject.getDelegate(groupPtr); - group.setScaleY(scaleY); - } - - @LayoutlibDelegate - static float nGetTranslateX(long groupPtr) { - VGroup_Delegate group = VNativeObject.getDelegate(groupPtr); - return group.getTranslateX(); - } - - @LayoutlibDelegate - static void nSetTranslateX(long groupPtr, float translateX) { - VGroup_Delegate group = VNativeObject.getDelegate(groupPtr); - group.setTranslateX(translateX); - } - - @LayoutlibDelegate - static float nGetTranslateY(long groupPtr) { - VGroup_Delegate group = VNativeObject.getDelegate(groupPtr); - return group.getTranslateY(); - } - - @LayoutlibDelegate - static void nSetTranslateY(long groupPtr, float translateY) { - VGroup_Delegate group = VNativeObject.getDelegate(groupPtr); - group.setTranslateY(translateY); - } - - @LayoutlibDelegate - static void nSetPathData(long pathPtr, long pathDataPtr) { - VPath_Delegate path = VNativeObject.getDelegate(pathPtr); - path.setPathData(PathParser_Delegate.getDelegate(pathDataPtr).getPathDataNodes()); - } - - @LayoutlibDelegate - static float nGetStrokeWidth(long pathPtr) { - VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr); - return path.getStrokeWidth(); - } - - @LayoutlibDelegate - static void nSetStrokeWidth(long pathPtr, float width) { - VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr); - path.setStrokeWidth(width); - } - - @LayoutlibDelegate - static int nGetStrokeColor(long pathPtr) { - VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr); - return path.getStrokeColor(); - } - - @LayoutlibDelegate - static void nSetStrokeColor(long pathPtr, int strokeColor) { - VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr); - path.setStrokeColor(strokeColor); - } - - @LayoutlibDelegate - static float nGetStrokeAlpha(long pathPtr) { - VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr); - return path.getStrokeAlpha(); - } - - @LayoutlibDelegate - static void nSetStrokeAlpha(long pathPtr, float alpha) { - VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr); - path.setStrokeAlpha(alpha); - } - - @LayoutlibDelegate - static int nGetFillColor(long pathPtr) { - VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr); - return path.getFillColor(); - } - - @LayoutlibDelegate - static void nSetFillColor(long pathPtr, int fillColor) { - VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr); - path.setFillColor(fillColor); - } - - @LayoutlibDelegate - static float nGetFillAlpha(long pathPtr) { - VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr); - return path.getFillAlpha(); - } - - @LayoutlibDelegate - static void nSetFillAlpha(long pathPtr, float fillAlpha) { - VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr); - path.setFillAlpha(fillAlpha); - } - - @LayoutlibDelegate - static float nGetTrimPathStart(long pathPtr) { - VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr); - return path.getTrimPathStart(); - } - - @LayoutlibDelegate - static void nSetTrimPathStart(long pathPtr, float trimPathStart) { - VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr); - path.setTrimPathStart(trimPathStart); - } - - @LayoutlibDelegate - static float nGetTrimPathEnd(long pathPtr) { - VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr); - return path.getTrimPathEnd(); - } - - @LayoutlibDelegate - static void nSetTrimPathEnd(long pathPtr, float trimPathEnd) { - VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr); - path.setTrimPathEnd(trimPathEnd); - } - - @LayoutlibDelegate - static float nGetTrimPathOffset(long pathPtr) { - VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr); - return path.getTrimPathOffset(); - } - - @LayoutlibDelegate - static void nSetTrimPathOffset(long pathPtr, float trimPathOffset) { - VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr); - path.setTrimPathOffset(trimPathOffset); - } - - /** - * Base class for all the internal Delegates that does two functions: - * <ol> - * <li>Serves as base class to store all the delegates in one {@link DelegateManager} - * <li>Provides setName for all the classes. {@link VPathRenderer_Delegate} does actually - * not need it - * </ol> - */ - abstract static class VNativeObject { - long mNativePtr = 0; - - @NonNull - static <T> T getDelegate(long nativePtr) { - //noinspection unchecked - T vNativeObject = (T) sPathManager.getDelegate(nativePtr); - - assert vNativeObject != null; - return vNativeObject; - } - - abstract void setName(String name); - - void setNativePtr(long nativePtr) { - mNativePtr = nativePtr; - } - - /** - * Method to explicitly dispose native objects - */ - void dispose() { - } - } - - private static class VClipPath_Delegate extends VPath_Delegate { - private VClipPath_Delegate() { - // Empty constructor. - } - - private VClipPath_Delegate(VClipPath_Delegate copy) { - super(copy); - } - - @Override - public boolean isClipPath() { - return true; - } - } - - static class VFullPath_Delegate extends VPath_Delegate { - // These constants need to be kept in sync with their values in VectorDrawable.VFullPath - private static final int STROKE_WIDTH_INDEX = 0; - private static final int STROKE_COLOR_INDEX = 1; - private static final int STROKE_ALPHA_INDEX = 2; - private static final int FILL_COLOR_INDEX = 3; - private static final int FILL_ALPHA_INDEX = 4; - private static final int TRIM_PATH_START_INDEX = 5; - private static final int TRIM_PATH_END_INDEX = 6; - private static final int TRIM_PATH_OFFSET_INDEX = 7; - private static final int STROKE_LINE_CAP_INDEX = 8; - private static final int STROKE_LINE_JOIN_INDEX = 9; - private static final int STROKE_MITER_LIMIT_INDEX = 10; - private static final int FILL_TYPE_INDEX = 11; - - private static final int LINECAP_BUTT = 0; - private static final int LINECAP_ROUND = 1; - private static final int LINECAP_SQUARE = 2; - - private static final int LINEJOIN_MITER = 0; - private static final int LINEJOIN_ROUND = 1; - private static final int LINEJOIN_BEVEL = 2; - - @NonNull - public Consumer<Float> getFloatPropertySetter(int propertyIdx) { - switch (propertyIdx) { - case STROKE_WIDTH_INDEX: - return this::setStrokeWidth; - case STROKE_ALPHA_INDEX: - return this::setStrokeAlpha; - case FILL_ALPHA_INDEX: - return this::setFillAlpha; - case TRIM_PATH_START_INDEX: - return this::setTrimPathStart; - case TRIM_PATH_END_INDEX: - return this::setTrimPathEnd; - case TRIM_PATH_OFFSET_INDEX: - return this::setTrimPathOffset; - } - - assert false : ("Invalid VFullPath_Delegate property index " + propertyIdx); - return t -> {}; - } - - @NonNull - public Consumer<Integer> getIntPropertySetter(int propertyIdx) { - switch (propertyIdx) { - case STROKE_COLOR_INDEX: - return this::setStrokeColor; - case FILL_COLOR_INDEX: - return this::setFillColor; - } - - assert false : ("Invalid VFullPath_Delegate property index " + propertyIdx); - return t -> {}; - } - - ///////////////////////////////////////////////////// - // Variables below need to be copied (deep copy if applicable) for mutation. - - int mStrokeColor = Color.TRANSPARENT; - float mStrokeWidth = 0; - - int mFillColor = Color.TRANSPARENT; - long mStrokeGradient = 0; - long mFillGradient = 0; - float mStrokeAlpha = 1.0f; - float mFillAlpha = 1.0f; - float mTrimPathStart = 0; - float mTrimPathEnd = 1; - float mTrimPathOffset = 0; - - Cap mStrokeLineCap = BUTT; - Join mStrokeLineJoin = MITER; - float mStrokeMiterlimit = 4; - - int mFillType = 0; // WINDING(0) is the default value. See Path.FillType - - private VFullPath_Delegate() { - // Empty constructor. - } - - private VFullPath_Delegate(VFullPath_Delegate copy) { - super(copy); - - mStrokeColor = copy.mStrokeColor; - mStrokeWidth = copy.mStrokeWidth; - mStrokeAlpha = copy.mStrokeAlpha; - mFillColor = copy.mFillColor; - mFillAlpha = copy.mFillAlpha; - mTrimPathStart = copy.mTrimPathStart; - mTrimPathEnd = copy.mTrimPathEnd; - mTrimPathOffset = copy.mTrimPathOffset; - - mStrokeLineCap = copy.mStrokeLineCap; - mStrokeLineJoin = copy.mStrokeLineJoin; - mStrokeMiterlimit = copy.mStrokeMiterlimit; - - mStrokeGradient = copy.mStrokeGradient; - mFillGradient = copy.mFillGradient; - mFillType = copy.mFillType; - } - - private int getStrokeLineCap() { - switch (mStrokeLineCap) { - case BUTT: - return LINECAP_BUTT; - case ROUND: - return LINECAP_ROUND; - case SQUARE: - return LINECAP_SQUARE; - default: - assert false; - } - - return -1; - } - - private void setStrokeLineCap(int cap) { - switch (cap) { - case LINECAP_BUTT: - mStrokeLineCap = BUTT; - break; - case LINECAP_ROUND: - mStrokeLineCap = ROUND; - break; - case LINECAP_SQUARE: - mStrokeLineCap = SQUARE; - break; - default: - assert false; - } - } - - private int getStrokeLineJoin() { - switch (mStrokeLineJoin) { - case MITER: - return LINEJOIN_MITER; - case ROUND: - return LINEJOIN_ROUND; - case BEVEL: - return LINEJOIN_BEVEL; - default: - assert false; - } - - return -1; - } - - private void setStrokeLineJoin(int join) { - switch (join) { - case LINEJOIN_BEVEL: - mStrokeLineJoin = BEVEL; - break; - case LINEJOIN_MITER: - mStrokeLineJoin = MITER; - break; - case LINEJOIN_ROUND: - mStrokeLineJoin = Join.ROUND; - break; - default: - assert false; - } - } - - private int getStrokeColor() { - return mStrokeColor; - } - - private void setStrokeColor(int strokeColor) { - mStrokeColor = strokeColor; - } - - private float getStrokeWidth() { - return mStrokeWidth; - } - - private void setStrokeWidth(float strokeWidth) { - mStrokeWidth = strokeWidth; - } - - private float getStrokeAlpha() { - return mStrokeAlpha; - } - - private void setStrokeAlpha(float strokeAlpha) { - mStrokeAlpha = strokeAlpha; - } - - private int getFillColor() { - return mFillColor; - } - - private void setFillColor(int fillColor) { - mFillColor = fillColor; - } - - private float getFillAlpha() { - return mFillAlpha; - } - - private void setFillAlpha(float fillAlpha) { - mFillAlpha = fillAlpha; - } - - private float getTrimPathStart() { - return mTrimPathStart; - } - - private void setTrimPathStart(float trimPathStart) { - mTrimPathStart = trimPathStart; - } - - private float getTrimPathEnd() { - return mTrimPathEnd; - } - - private void setTrimPathEnd(float trimPathEnd) { - mTrimPathEnd = trimPathEnd; - } - - private float getTrimPathOffset() { - return mTrimPathOffset; - } - - private void setTrimPathOffset(float trimPathOffset) { - mTrimPathOffset = trimPathOffset; - } - - private void setStrokeMiterlimit(float limit) { - mStrokeMiterlimit = limit; - } - - private float getStrokeMiterlimit() { - return mStrokeMiterlimit; - } - - private void setStrokeGradient(long gradientPtr) { - mStrokeGradient = gradientPtr; - } - - private void setFillGradient(long gradientPtr) { - mFillGradient = gradientPtr; - } - - private void setFillType(int fillType) { - mFillType = fillType; - } - - private int getFillType() { - return mFillType; - } - } - - static class VGroup_Delegate extends VNativeObject { - // This constants need to be kept in sync with their definitions in VectorDrawable.Group - private static final int ROTATE_INDEX = 0; - private static final int PIVOT_X_INDEX = 1; - private static final int PIVOT_Y_INDEX = 2; - private static final int SCALE_X_INDEX = 3; - private static final int SCALE_Y_INDEX = 4; - private static final int TRANSLATE_X_INDEX = 5; - private static final int TRANSLATE_Y_INDEX = 6; - - public Consumer<Float> getPropertySetter(int propertyIdx) { - switch (propertyIdx) { - case ROTATE_INDEX: - return this::setRotation; - case PIVOT_X_INDEX: - return this::setPivotX; - case PIVOT_Y_INDEX: - return this::setPivotY; - case SCALE_X_INDEX: - return this::setScaleX; - case SCALE_Y_INDEX: - return this::setScaleY; - case TRANSLATE_X_INDEX: - return this::setTranslateX; - case TRANSLATE_Y_INDEX: - return this::setTranslateY; - } - - assert false : ("Invalid VGroup_Delegate property index " + propertyIdx); - return t -> {}; - } - - ///////////////////////////////////////////////////// - // Variables below need to be copied (deep copy if applicable) for mutation. - final ArrayList<Object> mChildren = new ArrayList<>(); - // mStackedMatrix is only used temporarily when drawing, it combines all - // the parents' local matrices with the current one. - private final Matrix mStackedMatrix = new Matrix(); - // mLocalMatrix is updated based on the update of transformation information, - // either parsed from the XML or by animation. - private final Matrix mLocalMatrix = new Matrix(); - private float mRotate = 0; - private float mPivotX = 0; - private float mPivotY = 0; - private float mScaleX = 1; - private float mScaleY = 1; - private float mTranslateX = 0; - private float mTranslateY = 0; - private int mChangingConfigurations; - private String mGroupName = null; - - private VGroup_Delegate(VGroup_Delegate copy, ArrayMap<String, Object> targetsMap) { - mRotate = copy.mRotate; - mPivotX = copy.mPivotX; - mPivotY = copy.mPivotY; - mScaleX = copy.mScaleX; - mScaleY = copy.mScaleY; - mTranslateX = copy.mTranslateX; - mTranslateY = copy.mTranslateY; - mGroupName = copy.mGroupName; - mChangingConfigurations = copy.mChangingConfigurations; - if (mGroupName != null) { - targetsMap.put(mGroupName, this); - } - - mLocalMatrix.set(copy.mLocalMatrix); - } - - private VGroup_Delegate() { - } - - private void updateLocalMatrix() { - // The order we apply is the same as the - // RenderNode.cpp::applyViewPropertyTransforms(). - mLocalMatrix.reset(); - mLocalMatrix.postTranslate(-mPivotX, -mPivotY); - mLocalMatrix.postScale(mScaleX, mScaleY); - mLocalMatrix.postRotate(mRotate, 0, 0); - mLocalMatrix.postTranslate(mTranslateX + mPivotX, mTranslateY + mPivotY); - } - - /* Setters and Getters, used by animator from AnimatedVectorDrawable. */ - private float getRotation() { - return mRotate; - } - - private void setRotation(float rotation) { - if (rotation != mRotate) { - mRotate = rotation; - updateLocalMatrix(); - } - } - - private float getPivotX() { - return mPivotX; - } - - private void setPivotX(float pivotX) { - if (pivotX != mPivotX) { - mPivotX = pivotX; - updateLocalMatrix(); - } - } - - private float getPivotY() { - return mPivotY; - } - - private void setPivotY(float pivotY) { - if (pivotY != mPivotY) { - mPivotY = pivotY; - updateLocalMatrix(); - } - } - - private float getScaleX() { - return mScaleX; - } - - private void setScaleX(float scaleX) { - if (scaleX != mScaleX) { - mScaleX = scaleX; - updateLocalMatrix(); - } - } - - private float getScaleY() { - return mScaleY; - } - - private void setScaleY(float scaleY) { - if (scaleY != mScaleY) { - mScaleY = scaleY; - updateLocalMatrix(); - } - } - - private float getTranslateX() { - return mTranslateX; - } - - private void setTranslateX(float translateX) { - if (translateX != mTranslateX) { - mTranslateX = translateX; - updateLocalMatrix(); - } - } - - private float getTranslateY() { - return mTranslateY; - } - - private void setTranslateY(float translateY) { - if (translateY != mTranslateY) { - mTranslateY = translateY; - updateLocalMatrix(); - } - } - - @Override - public void setName(String name) { - mGroupName = name; - } - - @Override - protected void dispose() { - mChildren.stream().filter(child -> child instanceof VNativeObject).forEach(child - -> { - VNativeObject nativeObject = (VNativeObject) child; - if (nativeObject.mNativePtr != 0) { - sPathManager.removeJavaReferenceFor(nativeObject.mNativePtr); - nativeObject.mNativePtr = 0; - } - nativeObject.dispose(); - }); - mChildren.clear(); - } - - @Override - protected void finalize() throws Throwable { - super.finalize(); - } - } - - public static class VPath_Delegate extends VNativeObject { - protected PathParser_Delegate.PathDataNode[] mNodes = null; - String mPathName; - int mChangingConfigurations; - - public VPath_Delegate() { - // Empty constructor. - } - - public VPath_Delegate(VPath_Delegate copy) { - mPathName = copy.mPathName; - mChangingConfigurations = copy.mChangingConfigurations; - mNodes = copy.mNodes != null ? PathParser_Delegate.deepCopyNodes(copy.mNodes) : null; - } - - public void toPath(Path path) { - path.reset(); - if (mNodes != null) { - PathParser_Delegate.PathDataNode.nodesToPath(mNodes, - Path_Delegate.getDelegate(path.mNativePath)); - } - } - - @Override - public void setName(String name) { - mPathName = name; - } - - public boolean isClipPath() { - return false; - } - - private void setPathData(PathParser_Delegate.PathDataNode[] nodes) { - if (!PathParser_Delegate.canMorph(mNodes, nodes)) { - // This should not happen in the middle of animation. - mNodes = PathParser_Delegate.deepCopyNodes(nodes); - } else { - PathParser_Delegate.updateNodes(mNodes, nodes); - } - } - - @Override - void dispose() { - mNodes = null; - } - } - - static class VPathRenderer_Delegate extends VNativeObject { - /* Right now the internal data structure is organized as a tree. - * Each node can be a group node, or a path. - * A group node can have groups or paths as children, but a path node has - * no children. - * One example can be: - * Root Group - * / | \ - * Group Path Group - * / \ | - * Path Path Path - * - */ - // Variables that only used temporarily inside the draw() call, so there - // is no need for deep copying. - private final Path mPath; - private final Path mRenderPath; - private final Matrix mFinalPathMatrix = new Matrix(); - private final long mRootGroupPtr; - private float mViewportWidth = 0; - private float mViewportHeight = 0; - private float mRootAlpha = 1.0f; - private Paint mStrokePaint; - private Paint mFillPaint; - private PathMeasure mPathMeasure; - - private VPathRenderer_Delegate(long rootGroupPtr) { - mRootGroupPtr = rootGroupPtr; - mPath = new Path(); - mRenderPath = new Path(); - } - - private VPathRenderer_Delegate(VPathRenderer_Delegate rendererToCopy, - long rootGroupPtr) { - this(rootGroupPtr); - mViewportWidth = rendererToCopy.mViewportWidth; - mViewportHeight = rendererToCopy.mViewportHeight; - mRootAlpha = rendererToCopy.mRootAlpha; - } - - private float getRootAlpha() { - return mRootAlpha; - } - - void setRootAlpha(float alpha) { - mRootAlpha = alpha; - } - - private void drawGroupTree(VGroup_Delegate currentGroup, Matrix currentMatrix, - long canvasPtr, int w, int h, long filterPtr) { - // Calculate current group's matrix by preConcat the parent's and - // and the current one on the top of the stack. - // Basically the Mfinal = Mviewport * M0 * M1 * M2; - // Mi the local matrix at level i of the group tree. - currentGroup.mStackedMatrix.set(currentMatrix); - currentGroup.mStackedMatrix.preConcat(currentGroup.mLocalMatrix); - - // Save the current clip information, which is local to this group. - Canvas_Delegate.nSave(canvasPtr, MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG); - // Draw the group tree in the same order as the XML file. - for (int i = 0; i < currentGroup.mChildren.size(); i++) { - Object child = currentGroup.mChildren.get(i); - if (child instanceof VGroup_Delegate) { - VGroup_Delegate childGroup = (VGroup_Delegate) child; - drawGroupTree(childGroup, currentGroup.mStackedMatrix, - canvasPtr, w, h, filterPtr); - } else if (child instanceof VPath_Delegate) { - VPath_Delegate childPath = (VPath_Delegate) child; - drawPath(currentGroup, childPath, canvasPtr, w, h, filterPtr); - } - } - Canvas_Delegate.nRestore(canvasPtr); - } - - public void draw(long canvasPtr, long filterPtr, int w, int h) { - // Traverse the tree in pre-order to draw. - drawGroupTree(VNativeObject.getDelegate(mRootGroupPtr), Matrix.IDENTITY_MATRIX, canvasPtr, w, h, filterPtr); - } - - private void drawPath(VGroup_Delegate VGroup, VPath_Delegate VPath, long canvasPtr, - int w, - int h, - long filterPtr) { - final float scaleX = w / mViewportWidth; - final float scaleY = h / mViewportHeight; - final float minScale = Math.min(scaleX, scaleY); - final Matrix groupStackedMatrix = VGroup.mStackedMatrix; - - mFinalPathMatrix.set(groupStackedMatrix); - mFinalPathMatrix.postScale(scaleX, scaleY); - - final float matrixScale = getMatrixScale(groupStackedMatrix); - if (matrixScale == 0) { - // When either x or y is scaled to 0, we don't need to draw anything. - return; - } - VPath.toPath(mPath); - final Path path = mPath; - - mRenderPath.reset(); - - if (VPath.isClipPath()) { - mRenderPath.addPath(path, mFinalPathMatrix); - Canvas_Delegate.nClipPath(canvasPtr, mRenderPath.mNativePath, Op - .INTERSECT.nativeInt); - } else { - VFullPath_Delegate fullPath = (VFullPath_Delegate) VPath; - if (fullPath.mTrimPathStart != 0.0f || fullPath.mTrimPathEnd != 1.0f) { - float start = (fullPath.mTrimPathStart + fullPath.mTrimPathOffset) % 1.0f; - float end = (fullPath.mTrimPathEnd + fullPath.mTrimPathOffset) % 1.0f; - - if (mPathMeasure == null) { - mPathMeasure = new PathMeasure(); - } - mPathMeasure.setPath(mPath, false); - - float len = mPathMeasure.getLength(); - start = start * len; - end = end * len; - path.reset(); - if (start > end) { - mPathMeasure.getSegment(start, len, path, true); - mPathMeasure.getSegment(0f, end, path, true); - } else { - mPathMeasure.getSegment(start, end, path, true); - } - path.rLineTo(0, 0); // fix bug in measure - } - mRenderPath.addPath(path, mFinalPathMatrix); - - if (fullPath.mFillColor != Color.TRANSPARENT) { - if (mFillPaint == null) { - mFillPaint = new Paint(); - mFillPaint.setStyle(Style.FILL); - mFillPaint.setAntiAlias(true); - } - - final Paint fillPaint = mFillPaint; - fillPaint.setColor(applyAlpha(applyAlpha(fullPath.mFillColor, fullPath - .mFillAlpha), getRootAlpha())); - Paint_Delegate fillPaintDelegate = Paint_Delegate.getDelegate(fillPaint - .getNativeInstance()); - // mFillPaint can not be null at this point so we will have a delegate - assert fillPaintDelegate != null; - fillPaintDelegate.setColorFilter(filterPtr); - fillPaintDelegate.setShader(fullPath.mFillGradient); - Path_Delegate.nSetFillType(mRenderPath.mNativePath, fullPath.mFillType); - BaseCanvas_Delegate.nDrawPath(canvasPtr, mRenderPath.mNativePath, fillPaint - .getNativeInstance()); - } - - if (fullPath.mStrokeColor != Color.TRANSPARENT) { - if (mStrokePaint == null) { - mStrokePaint = new Paint(); - mStrokePaint.setStyle(Style.STROKE); - mStrokePaint.setAntiAlias(true); - } - - final Paint strokePaint = mStrokePaint; - if (fullPath.mStrokeLineJoin != null) { - strokePaint.setStrokeJoin(fullPath.mStrokeLineJoin); - } - - if (fullPath.mStrokeLineCap != null) { - strokePaint.setStrokeCap(fullPath.mStrokeLineCap); - } - - strokePaint.setStrokeMiter(fullPath.mStrokeMiterlimit); - strokePaint.setColor(applyAlpha(applyAlpha(fullPath.mStrokeColor, fullPath - .mStrokeAlpha), getRootAlpha())); - Paint_Delegate strokePaintDelegate = Paint_Delegate.getDelegate(strokePaint - .getNativeInstance()); - // mStrokePaint can not be null at this point so we will have a delegate - assert strokePaintDelegate != null; - strokePaintDelegate.setColorFilter(filterPtr); - final float finalStrokeScale = minScale * matrixScale; - strokePaint.setStrokeWidth(fullPath.mStrokeWidth * finalStrokeScale); - strokePaintDelegate.setShader(fullPath.mStrokeGradient); - BaseCanvas_Delegate.nDrawPath(canvasPtr, mRenderPath.mNativePath, strokePaint - .getNativeInstance()); - } - } - } - - private float getMatrixScale(Matrix groupStackedMatrix) { - // Given unit vectors A = (0, 1) and B = (1, 0). - // After matrix mapping, we got A' and B'. Let theta = the angel b/t A' and B'. - // Therefore, the final scale we want is min(|A'| * sin(theta), |B'| * sin(theta)), - // which is (|A'| * |B'| * sin(theta)) / max (|A'|, |B'|); - // If max (|A'|, |B'|) = 0, that means either x or y has a scale of 0. - // - // For non-skew case, which is most of the cases, matrix scale is computing exactly the - // scale on x and y axis, and take the minimal of these two. - // For skew case, an unit square will mapped to a parallelogram. And this function will - // return the minimal height of the 2 bases. - float[] unitVectors = new float[]{0, 1, 1, 0}; - groupStackedMatrix.mapVectors(unitVectors); - float scaleX = MathUtils.mag(unitVectors[0], unitVectors[1]); - float scaleY = MathUtils.mag(unitVectors[2], unitVectors[3]); - float crossProduct = MathUtils.cross(unitVectors[0], unitVectors[1], - unitVectors[2], unitVectors[3]); - float maxScale = MathUtils.max(scaleX, scaleY); - - float matrixScale = 0; - if (maxScale > 0) { - matrixScale = MathUtils.abs(crossProduct) / maxScale; - } - if (DBG_VECTOR_DRAWABLE) { - Log.d(LOGTAG, "Scale x " + scaleX + " y " + scaleY + " final " + matrixScale); - } - return matrixScale; - } - - @Override - public void setName(String name) { - } - - @Override - protected void finalize() throws Throwable { - // The mRootGroupPtr is not explicitly freed by anything in the VectorDrawable so we - // need to free it here. - VNativeObject nativeObject = sPathManager.getDelegate(mRootGroupPtr); - sPathManager.removeJavaReferenceFor(mRootGroupPtr); - assert nativeObject != null; - nativeObject.dispose(); - - super.finalize(); - } - } -} diff --git a/tools/layoutlib/bridge/src/android/os/HandlerThread_Delegate.java b/tools/layoutlib/bridge/src/android/os/HandlerThread_Delegate.java deleted file mode 100644 index afbe97c06ebb..000000000000 --- a/tools/layoutlib/bridge/src/android/os/HandlerThread_Delegate.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2011 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.os; - -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.impl.RenderAction; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Delegate overriding selected methods of android.os.HandlerThread - * - * Through the layoutlib_create tool, selected methods of Handler have been replaced - * by calls to methods of the same name in this delegate class. - * - * - */ -public class HandlerThread_Delegate { - - private static Map<BridgeContext, List<HandlerThread>> sThreads = - new HashMap<BridgeContext, List<HandlerThread>>(); - - public static void cleanUp(BridgeContext context) { - List<HandlerThread> list = sThreads.get(context); - if (list != null) { - for (HandlerThread thread : list) { - thread.quit(); - } - - list.clear(); - sThreads.remove(context); - } - } - - // -------- Delegate methods - - @LayoutlibDelegate - /*package*/ static void run(HandlerThread theThread) { - // record the thread so that it can be quit() on clean up. - BridgeContext context = RenderAction.getCurrentContext(); - List<HandlerThread> list = sThreads.get(context); - if (list == null) { - list = new ArrayList<HandlerThread>(); - sThreads.put(context, list); - } - - list.add(theThread); - - // ---- START DEFAULT IMPLEMENTATION. - - theThread.mTid = Process.myTid(); - Looper.prepare(); - synchronized (theThread) { - theThread.mLooper = Looper.myLooper(); - theThread.notifyAll(); - } - Process.setThreadPriority(theThread.mPriority); - theThread.onLooperPrepared(); - Looper.loop(); - theThread.mTid = -1; - } -} diff --git a/tools/layoutlib/bridge/src/android/os/Handler_Delegate.java b/tools/layoutlib/bridge/src/android/os/Handler_Delegate.java deleted file mode 100644 index 2152c8ad19ae..000000000000 --- a/tools/layoutlib/bridge/src/android/os/Handler_Delegate.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.os; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - - -/** - * Delegate overriding selected methods of android.os.Handler - * - * Through the layoutlib_create tool, selected methods of Handler have been replaced - * by calls to methods of the same name in this delegate class. - * - * - */ -public class Handler_Delegate { - - // -------- Delegate methods - - @LayoutlibDelegate - /*package*/ static boolean sendMessageAtTime(Handler handler, Message msg, long uptimeMillis) { - // get the callback - IHandlerCallback callback = sCallbacks.get(); - if (callback != null) { - callback.sendMessageAtTime(handler, msg, uptimeMillis); - } - return true; - } - - // -------- Delegate implementation - - public interface IHandlerCallback { - void sendMessageAtTime(Handler handler, Message msg, long uptimeMillis); - } - - private final static ThreadLocal<IHandlerCallback> sCallbacks = - new ThreadLocal<IHandlerCallback>(); - - public static void setCallback(IHandlerCallback callback) { - sCallbacks.set(callback); - } - -} diff --git a/tools/layoutlib/bridge/src/android/os/Looper_Accessor.java b/tools/layoutlib/bridge/src/android/os/Looper_Accessor.java deleted file mode 100644 index 09f3e47d7a14..000000000000 --- a/tools/layoutlib/bridge/src/android/os/Looper_Accessor.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2011 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.os; - -import java.lang.reflect.Field; - -/** - * Class allowing access to package-protected methods/fields. - */ -public class Looper_Accessor { - - public static void cleanupThread() { - // clean up the looper - Looper.sThreadLocal.remove(); - try { - Field sMainLooper = Looper.class.getDeclaredField("sMainLooper"); - sMainLooper.setAccessible(true); - sMainLooper.set(null, null); - } catch (SecurityException e) { - catchReflectionException(); - } catch (IllegalArgumentException e) { - catchReflectionException(); - } catch (NoSuchFieldException e) { - catchReflectionException(); - } catch (IllegalAccessException e) { - catchReflectionException(); - } - - } - - private static void catchReflectionException() { - assert(false); - } -} diff --git a/tools/layoutlib/bridge/src/android/os/ServiceManager.java b/tools/layoutlib/bridge/src/android/os/ServiceManager.java deleted file mode 100644 index 34c78455f85d..000000000000 --- a/tools/layoutlib/bridge/src/android/os/ServiceManager.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2009 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.os; - -import java.util.Map; - -public final class ServiceManager { - - /** - * Returns a reference to a service with the given name. - * - * @param name the name of the service to get - * @return a reference to the service, or <code>null</code> if the service doesn't exist - */ - public static IBinder getService(String name) { - return null; - } - - /** - * Is not supposed to return null, but that is fine for layoutlib. - */ - public static IBinder getServiceOrThrow(String name) throws ServiceNotFoundException { - throw new ServiceNotFoundException(name); - } - - /** - * Place a new @a service called @a name into the service - * manager. - * - * @param name the name of the new service - * @param service the service object - */ - public static void addService(String name, IBinder service) { - // pass - } - - /** - * Retrieve an existing service called @a name from the - * service manager. Non-blocking. - */ - public static IBinder checkService(String name) { - return null; - } - - /** - * Return a list of all currently running services. - * @return an array of all currently running services, or <code>null</code> in - * case of an exception - */ - public static String[] listServices() { - // actual implementation returns null sometimes, so it's ok - // to return null instead of an empty list. - return null; - } - - /** - * This is only intended to be called when the process is first being brought - * up and bound by the activity manager. There is only one thread in the process - * at that time, so no locking is done. - * - * @param cache the cache of service references - * @hide - */ - public static void initServiceCache(Map<String, IBinder> cache) { - // pass - } - - /** - * Exception thrown when no service published for given name. This might be - * thrown early during boot before certain services have published - * themselves. - * - * @hide - */ - public static class ServiceNotFoundException extends Exception { - // identical to the original implementation - public ServiceNotFoundException(String name) { - super("No service published for: " + name); - } - } -} diff --git a/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java b/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java deleted file mode 100644 index 9677aaf5d07a..000000000000 --- a/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.os; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; -import com.android.tools.layoutlib.java.System_Delegate; - -/** - * Delegate implementing the native methods of android.os.SystemClock - * - * Through the layoutlib_create tool, the original native methods of SystemClock have been replaced - * by calls to methods of the same name in this delegate class. - * - * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager} - * around to map int to instance of the delegate. - * - */ -public class SystemClock_Delegate { - /** - * Returns milliseconds since boot, not counting time spent in deep sleep. - * <b>Note:</b> This value may get reset occasionally (before it would - * otherwise wrap around). - * - * @return milliseconds of non-sleep uptime since boot. - */ - @LayoutlibDelegate - /*package*/ static long uptimeMillis() { - return System_Delegate.currentTimeMillis() - System_Delegate.bootTimeMillis(); - } - - /** - * Returns milliseconds since boot, including time spent in sleep. - * - * @return elapsed milliseconds since boot. - */ - @LayoutlibDelegate - /*package*/ static long elapsedRealtime() { - return System_Delegate.currentTimeMillis() - System_Delegate.bootTimeMillis(); - } - - /** - * Returns nanoseconds since boot, including time spent in sleep. - * - * @return elapsed nanoseconds since boot. - */ - @LayoutlibDelegate - /*package*/ static long elapsedRealtimeNanos() { - return System_Delegate.nanoTime() - System_Delegate.bootTime(); - } - - /** - * Returns milliseconds running in the current thread. - * - * @return elapsed milliseconds in the thread - */ - @LayoutlibDelegate - /*package*/ static long currentThreadTimeMillis() { - return System_Delegate.currentTimeMillis(); - } - - /** - * Returns microseconds running in the current thread. - * - * @return elapsed microseconds in the thread - * - * @hide - */ - @LayoutlibDelegate - /*package*/ static long currentThreadTimeMicro() { - return System_Delegate.currentTimeMillis() * 1000; - } - - /** - * Returns current wall time in microseconds. - * - * @return elapsed microseconds in wall time - * - * @hide - */ - @LayoutlibDelegate - /*package*/ static long currentTimeMicro() { - return elapsedRealtime() * 1000; - } -} diff --git a/tools/layoutlib/bridge/src/android/os/SystemProperties_Delegate.java b/tools/layoutlib/bridge/src/android/os/SystemProperties_Delegate.java deleted file mode 100644 index d299add05eab..000000000000 --- a/tools/layoutlib/bridge/src/android/os/SystemProperties_Delegate.java +++ /dev/null @@ -1,110 +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.os; - -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import java.util.Map; - -/** - * Delegate implementing the native methods of android.os.SystemProperties - * - * Through the layoutlib_create tool, the original native methods of SystemProperties have been - * replaced by calls to methods of the same name in this delegate class. - * - * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager} - * around to map int to instance of the delegate. - */ -public class SystemProperties_Delegate { - - @LayoutlibDelegate - /*package*/ static String native_get(String key) { - return native_get(key, ""); - } - - @LayoutlibDelegate - /*package*/ static String native_get(String key, String def) { - Map<String, String> properties = Bridge.getPlatformProperties(); - String value = properties.get(key); - if (value != null) { - return value; - } - - return def; - } - @LayoutlibDelegate - /*package*/ static int native_get_int(String key, int def) { - Map<String, String> properties = Bridge.getPlatformProperties(); - String value = properties.get(key); - if (value != null) { - return Integer.decode(value); - } - - return def; - } - - @LayoutlibDelegate - /*package*/ static long native_get_long(String key, long def) { - Map<String, String> properties = Bridge.getPlatformProperties(); - String value = properties.get(key); - if (value != null) { - return Long.decode(value); - } - - return def; - } - - /** - * Values 'n', 'no', '0', 'false' or 'off' are considered false. - * Values 'y', 'yes', '1', 'true' or 'on' are considered true. - */ - @LayoutlibDelegate - /*package*/ static boolean native_get_boolean(String key, boolean def) { - Map<String, String> properties = Bridge.getPlatformProperties(); - String value = properties.get(key); - - if ("n".equals(value) || "no".equals(value) || "0".equals(value) || "false".equals(value) - || "off".equals(value)) { - return false; - } - //noinspection SimplifiableIfStatement - if ("y".equals(value) || "yes".equals(value) || "1".equals(value) || "true".equals(value) - || "on".equals(value)) { - return true; - } - - return def; - } - - @LayoutlibDelegate - /*package*/ static void native_set(String key, String def) { - Map<String, String> properties = Bridge.getPlatformProperties(); - properties.put(key, def); - } - - @LayoutlibDelegate - /*package*/ static void native_add_change_callback() { - // pass. - } - - @LayoutlibDelegate - /*package*/ static void native_report_sysprop_change() { - // pass. - } -} diff --git a/tools/layoutlib/bridge/src/android/preference/BridgePreferenceInflater.java b/tools/layoutlib/bridge/src/android/preference/BridgePreferenceInflater.java deleted file mode 100644 index aa393a976d12..000000000000 --- a/tools/layoutlib/bridge/src/android/preference/BridgePreferenceInflater.java +++ /dev/null @@ -1,61 +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.preference; - -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.InflateException; - -public class BridgePreferenceInflater extends PreferenceInflater { - - public BridgePreferenceInflater(Context context, PreferenceManager preferenceManager) { - super(context, preferenceManager); - } - - @Override - protected Preference onCreateItem(String name, AttributeSet attrs) - throws ClassNotFoundException { - Object viewKey = null; - BridgeContext bc = null; - - Context context = getContext(); - if (context instanceof BridgeContext) { - bc = (BridgeContext) context; - } - if (attrs instanceof BridgeXmlBlockParser) { - viewKey = ((BridgeXmlBlockParser) attrs).getViewCookie(); - } - - Preference preference = null; - try { - preference = super.onCreateItem(name, attrs); - } catch (ClassNotFoundException | InflateException exception) { - // name is probably not a valid preference type - if ("SwitchPreferenceCompat".equals(name)) { - preference = super.onCreateItem("SwitchPreference", attrs); - } - } - - if (viewKey != null && bc != null) { - bc.addCookie(preference, viewKey); - } - return preference; - } -} diff --git a/tools/layoutlib/bridge/src/android/preference/Preference_Delegate.java b/tools/layoutlib/bridge/src/android/preference/Preference_Delegate.java deleted file mode 100644 index 2e44a7770aae..000000000000 --- a/tools/layoutlib/bridge/src/android/preference/Preference_Delegate.java +++ /dev/null @@ -1,80 +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.preference; - -import com.android.internal.R; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import org.xmlpull.v1.XmlPullParser; - -import android.content.Context; -import android.content.res.TypedArray; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ListView; - -/** - * Delegate that provides implementation for native methods in {@link Preference} - * <p/> - * Through the layoutlib_create tool, selected methods of Preference have been replaced by calls to - * methods of the same name in this delegate class. - */ -public class Preference_Delegate { - - @LayoutlibDelegate - /*package*/ static View getView(Preference pref, View convertView, ViewGroup parent) { - Context context = pref.getContext(); - BridgeContext bc = context instanceof BridgeContext ? ((BridgeContext) context) : null; - convertView = pref.getView_Original(convertView, parent); - if (bc != null) { - Object cookie = bc.getCookie(pref); - if (cookie != null) { - bc.addViewKey(convertView, cookie); - } - } - return convertView; - } - - /** - * Inflates the parser and returns the ListView containing the Preferences. - */ - public static View inflatePreference(Context context, XmlPullParser parser, ViewGroup root) { - PreferenceManager pm = new PreferenceManager(context); - PreferenceInflater inflater = new BridgePreferenceInflater(context, pm); - PreferenceScreen ps = (PreferenceScreen) inflater.inflate(parser, null, true); - pm.setPreferences(ps); - ListView preferenceView = createContainerView(context, root); - ps.bind(preferenceView); - return preferenceView; - } - - private static ListView createContainerView(Context context, ViewGroup root) { - TypedArray a = context.obtainStyledAttributes(null, R.styleable.PreferenceFragment, - R.attr.preferenceFragmentStyle, 0); - int mLayoutResId = a.getResourceId(R.styleable.PreferenceFragment_layout, - R.layout.preference_list_fragment); - a.recycle(); - - LayoutInflater inflater = - (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - inflater.inflate(mLayoutResId, root, true); - - return (ListView) root.findViewById(android.R.id.list); - } -} diff --git a/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java b/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java deleted file mode 100644 index 38171dc06795..000000000000 --- a/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2011 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.ide.common.rendering.api.LayoutLog; -import com.android.layoutlib.bridge.Bridge; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.icu.text.Bidi; - -/** - * Delegate used to provide new implementation for the native methods of {@link AndroidBidi} - * - * Through the layoutlib_create tool, the original methods of AndroidBidi have been replaced - * by calls to methods of the same name in this delegate class. - * - */ -public class AndroidBidi_Delegate { - - @LayoutlibDelegate - /*package*/ static int runBidi(int dir, char[] chars, byte[] charInfo, int count, - boolean haveInfo) { - - switch (dir) { - case 0: // Layout.DIR_REQUEST_LTR - dir = Bidi.LTR; - break; - case 1: // Layout.DIR_REQUEST_RTL - dir = Bidi.RTL; - break; - case -1: // Layout.DIR_REQUEST_DEFAULT_RTL - dir = Bidi.LEVEL_DEFAULT_RTL; - break; - case -2: // Layout.DIR_REQUEST_DEFAULT_LTR - dir = Bidi.LEVEL_DEFAULT_LTR; - break; - default: - // Invalid code. Log error, assume LEVEL_DEFAULT_LTR and continue. - Bridge.getLog().error(LayoutLog.TAG_BROKEN, "Invalid direction flag", null); - dir = Bidi.LEVEL_DEFAULT_LTR; - } - Bidi bidi = new Bidi(chars, 0, null, 0, count, dir); - if (charInfo != null) { - for (int i = 0; i < count; ++i) - charInfo[i] = bidi.getLevelAt(i); - } - return bidi.getParaLevel(); - } -} diff --git a/tools/layoutlib/bridge/src/android/text/GreedyLineBreaker.java b/tools/layoutlib/bridge/src/android/text/GreedyLineBreaker.java deleted file mode 100644 index 50289e9fb447..000000000000 --- a/tools/layoutlib/bridge/src/android/text/GreedyLineBreaker.java +++ /dev/null @@ -1,192 +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.text; - -import android.annotation.NonNull; -import android.text.Primitive.PrimitiveType; -import android.text.StaticLayout.LineBreaks; - -import java.util.ArrayList; -import java.util.List; - -import static android.text.Primitive.PrimitiveType.PENALTY_INFINITY; - -// Based on the native implementation of GreedyLineBreaker in -// frameworks/base/core/jni/android_text_StaticLayout.cpp revision b808260 -public class GreedyLineBreaker extends LineBreaker { - - public GreedyLineBreaker(@NonNull List<Primitive> primitives, @NonNull LineWidth lineWidth, - @NonNull TabStops tabStops) { - super(primitives, lineWidth, tabStops); - } - - @Override - public void computeBreaks(@NonNull LineBreaks lineBreaks) { - BreakInfo breakInfo = new BreakInfo(); - int lineNum = 0; - float width = 0, printedWidth = 0; - boolean breakFound = false, goodBreakFound = false; - int breakIndex = 0, goodBreakIndex = 0; - float breakWidth = 0, goodBreakWidth = 0; - int firstTabIndex = Integer.MAX_VALUE; - - float maxWidth = mLineWidth.getLineWidth(lineNum); - - int numPrimitives = mPrimitives.size(); - // greedily fit as many characters as possible on each line - // loop over all primitives, and choose the best break point - // (if possible, a break point without splitting a word) - // after going over the maximum length - for (int i = 0; i < numPrimitives; i++) { - Primitive p = mPrimitives.get(i); - - // update the current line width - if (p.type == PrimitiveType.BOX || p.type == PrimitiveType.GLUE) { - width += p.width; - if (p.type == PrimitiveType.BOX) { - printedWidth = width; - } - } else if (p.type == PrimitiveType.VARIABLE) { - width = mTabStops.width(width); - // keep track of first tab character in the region we are examining - // so we can determine whether or not a line contains a tab - firstTabIndex = Math.min(firstTabIndex, i); - } - - // find the best break point for the characters examined so far - if (printedWidth > maxWidth) { - //noinspection StatementWithEmptyBody - if (breakFound || goodBreakFound) { - if (goodBreakFound) { - // a true line break opportunity existed in the characters examined so far, - // so there is no need to split a word - i = goodBreakIndex; // no +1 because of i++ - lineNum++; - maxWidth = mLineWidth.getLineWidth(lineNum); - breakInfo.mBreaksList.add(mPrimitives.get(goodBreakIndex).location); - breakInfo.mWidthsList.add(goodBreakWidth); - breakInfo.mFlagsList.add(firstTabIndex < goodBreakIndex); - firstTabIndex = Integer.MAX_VALUE; - } else { - // must split a word because there is no other option - i = breakIndex; // no +1 because of i++ - lineNum++; - maxWidth = mLineWidth.getLineWidth(lineNum); - breakInfo.mBreaksList.add(mPrimitives.get(breakIndex).location); - breakInfo.mWidthsList.add(breakWidth); - breakInfo.mFlagsList.add(firstTabIndex < breakIndex); - firstTabIndex = Integer.MAX_VALUE; - } - printedWidth = width = 0; - goodBreakFound = breakFound = false; - goodBreakWidth = breakWidth = 0; - continue; - } else { - // no choice, keep going... must make progress by putting at least one - // character on a line, even if part of that character is cut off -- - // there is no other option - } - } - - // update possible break points - if (p.type == PrimitiveType.PENALTY && - p.penalty < PENALTY_INFINITY) { - // this does not handle penalties with width - - // handle forced line break - if (p.penalty == -PENALTY_INFINITY) { - lineNum++; - maxWidth = mLineWidth.getLineWidth(lineNum); - breakInfo.mBreaksList.add(p.location); - breakInfo.mWidthsList.add(printedWidth); - breakInfo.mFlagsList.add(firstTabIndex < i); - firstTabIndex = Integer.MAX_VALUE; - printedWidth = width = 0; - goodBreakFound = breakFound = false; - goodBreakWidth = breakWidth = 0; - continue; - } - if (i > breakIndex && (printedWidth <= maxWidth || !breakFound)) { - breakFound = true; - breakIndex = i; - breakWidth = printedWidth; - } - if (i > goodBreakIndex && printedWidth <= maxWidth) { - goodBreakFound = true; - goodBreakIndex = i; - goodBreakWidth = printedWidth; - } - } else if (p.type == PrimitiveType.WORD_BREAK) { - // only do this if necessary -- we don't want to break words - // when possible, but sometimes it is unavoidable - if (i > breakIndex && (printedWidth <= maxWidth || !breakFound)) { - breakFound = true; - breakIndex = i; - breakWidth = printedWidth; - } - } - } - - if (breakFound || goodBreakFound) { - // output last break if there are more characters to output - if (goodBreakFound) { - breakInfo.mBreaksList.add(mPrimitives.get(goodBreakIndex).location); - breakInfo.mWidthsList.add(goodBreakWidth); - breakInfo.mFlagsList.add(firstTabIndex < goodBreakIndex); - } else { - breakInfo.mBreaksList.add(mPrimitives.get(breakIndex).location); - breakInfo.mWidthsList.add(breakWidth); - breakInfo.mFlagsList.add(firstTabIndex < breakIndex); - } - } - breakInfo.copyTo(lineBreaks); - } - - private static class BreakInfo { - List<Integer> mBreaksList = new ArrayList<Integer>(); - List<Float> mWidthsList = new ArrayList<Float>(); - List<Boolean> mFlagsList = new ArrayList<Boolean>(); - - public void copyTo(LineBreaks lineBreaks) { - if (lineBreaks.breaks.length != mBreaksList.size()) { - lineBreaks.breaks = new int[mBreaksList.size()]; - lineBreaks.widths = new float[mWidthsList.size()]; - lineBreaks.flags = new int[mFlagsList.size()]; - } - - int i = 0; - for (int b : mBreaksList) { - lineBreaks.breaks[i] = b; - i++; - } - i = 0; - for (float b : mWidthsList) { - lineBreaks.widths[i] = b; - i++; - } - i = 0; - for (boolean b : mFlagsList) { - lineBreaks.flags[i] = b ? TAB_MASK : 0; - i++; - } - - mBreaksList = null; - mWidthsList = null; - mFlagsList = null; - } - } -} diff --git a/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java b/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java deleted file mode 100644 index 499e58a5d4e5..000000000000 --- a/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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; -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 Hyphenator 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*/ @SuppressWarnings("UnusedParameters") // TODO implement this. - static long loadHyphenator(ByteBuffer buffer, int offset, int minPrefix, int minSuffix) { - 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 deleted file mode 100644 index 06e9c845c2f6..000000000000 --- a/tools/layoutlib/bridge/src/android/text/LineBreaker.java +++ /dev/null @@ -1,43 +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.text; - -import android.annotation.NonNull; -import android.text.StaticLayout.LineBreaks; - -import java.util.Collections; -import java.util.List; - -// Based on the native implementation of LineBreaker in -// frameworks/base/core/jni/android_text_StaticLayout.cpp revision b808260 -public abstract class LineBreaker { - - protected static final int TAB_MASK = 0x20000000; // keep in sync with StaticLayout - - protected final @NonNull List<Primitive> mPrimitives; - protected final @NonNull LineWidth mLineWidth; - protected final @NonNull TabStops mTabStops; - - public LineBreaker(@NonNull List<Primitive> primitives, @NonNull LineWidth lineWidth, - @NonNull TabStops tabStops) { - mPrimitives = Collections.unmodifiableList(primitives); - mLineWidth = lineWidth; - mTabStops = tabStops; - } - - public abstract void computeBreaks(@NonNull LineBreaks breakInfo); -} diff --git a/tools/layoutlib/bridge/src/android/text/LineWidth.java b/tools/layoutlib/bridge/src/android/text/LineWidth.java deleted file mode 100644 index 2ea886df88a4..000000000000 --- a/tools/layoutlib/bridge/src/android/text/LineWidth.java +++ /dev/null @@ -1,35 +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.text; - -// Based on the native implementation of LineWidth in -// frameworks/base/core/jni/android_text_StaticLayout.cpp revision b808260 -public class LineWidth { - private final float mFirstWidth; - private final int mFirstWidthLineCount; - private float mRestWidth; - - public LineWidth(float firstWidth, int firstWidthLineCount, float restWidth) { - mFirstWidth = firstWidth; - mFirstWidthLineCount = firstWidthLineCount; - mRestWidth = restWidth; - } - - public float getLineWidth(int line) { - return (line < mFirstWidthLineCount) ? mFirstWidth : mRestWidth; - } -} diff --git a/tools/layoutlib/bridge/src/android/text/OptimizingLineBreaker.java b/tools/layoutlib/bridge/src/android/text/OptimizingLineBreaker.java deleted file mode 100644 index ed8e33ae3e9a..000000000000 --- a/tools/layoutlib/bridge/src/android/text/OptimizingLineBreaker.java +++ /dev/null @@ -1,261 +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.text; - -import android.annotation.NonNull; -import android.text.Primitive.PrimitiveType; -import android.text.StaticLayout.LineBreaks; - -import java.util.ArrayList; -import java.util.List; -import java.util.ListIterator; - -import static android.text.Primitive.PrimitiveType.PENALTY_INFINITY; - - -// Based on the native implementation of OptimizingLineBreaker in -// frameworks/base/core/jni/android_text_StaticLayout.cpp revision b808260 -/** - * A more complex version of line breaking where we try to prevent the right edge from being too - * jagged. - */ -public class OptimizingLineBreaker extends LineBreaker { - - public OptimizingLineBreaker(@NonNull List<Primitive> primitives, @NonNull LineWidth lineWidth, - @NonNull TabStops tabStops) { - super(primitives, lineWidth, tabStops); - } - - @Override - public void computeBreaks(@NonNull LineBreaks breakInfo) { - int numBreaks = mPrimitives.size(); - assert numBreaks > 0; - if (numBreaks == 1) { - // This can be true only if it's an empty paragraph. - Primitive p = mPrimitives.get(0); - assert p.type == PrimitiveType.PENALTY; - breakInfo.breaks = new int[]{0}; - breakInfo.widths = new float[]{p.width}; - breakInfo.flags = new int[]{0}; - return; - } - Node[] opt = new Node[numBreaks]; - opt[0] = new Node(-1, 0, 0, 0, false); - opt[numBreaks - 1] = new Node(-1, 0, 0, 0, false); - - ArrayList<Integer> active = new ArrayList<Integer>(); - active.add(0); - int lastBreak = 0; - for (int i = 0; i < numBreaks; i++) { - Primitive p = mPrimitives.get(i); - if (p.type == PrimitiveType.PENALTY) { - boolean finalBreak = (i + 1 == numBreaks); - Node bestBreak = null; - - for (ListIterator<Integer> it = active.listIterator(); it.hasNext(); - /* incrementing done in loop */) { - int pos = it.next(); - int lines = opt[pos].mPrevCount; - float maxWidth = mLineWidth.getLineWidth(lines); - // we have to compute metrics every time -- - // we can't really pre-compute this stuff and just deal with breaks - // because of the way tab characters work, this makes it computationally - // harder, but this way, we can still optimize while treating tab characters - // correctly - LineMetrics lineMetrics = computeMetrics(pos, i); - if (lineMetrics.mPrintedWidth <= maxWidth) { - float demerits = computeDemerits(maxWidth, lineMetrics.mPrintedWidth, - finalBreak, p.penalty) + opt[pos].mDemerits; - if (bestBreak == null || demerits < bestBreak.mDemerits) { - if (bestBreak == null) { - bestBreak = new Node(pos, opt[pos].mPrevCount + 1, demerits, - lineMetrics.mPrintedWidth, lineMetrics.mHasTabs); - } else { - bestBreak.mPrev = pos; - bestBreak.mPrevCount = opt[pos].mPrevCount + 1; - bestBreak.mDemerits = demerits; - bestBreak.mWidth = lineMetrics.mPrintedWidth; - bestBreak.mHasTabs = lineMetrics.mHasTabs; - } - } - } else { - it.remove(); - } - } - if (p.penalty == -PENALTY_INFINITY) { - active.clear(); - } - if (bestBreak != null) { - opt[i] = bestBreak; - active.add(i); - lastBreak = i; - } - if (active.isEmpty()) { - // we can't give up! - LineMetrics lineMetrics = new LineMetrics(); - int lines = opt[lastBreak].mPrevCount; - float maxWidth = mLineWidth.getLineWidth(lines); - int breakIndex = desperateBreak(lastBreak, numBreaks, maxWidth, lineMetrics); - opt[breakIndex] = new Node(lastBreak, lines + 1, 0 /*doesn't matter*/, - lineMetrics.mWidth, lineMetrics.mHasTabs); - active.add(breakIndex); - lastBreak = breakIndex; - i = breakIndex; // incremented by i++ - } - } - } - - int idx = numBreaks - 1; - int count = opt[idx].mPrevCount; - resize(breakInfo, count); - while (opt[idx].mPrev != -1) { - count--; - assert count >=0; - - breakInfo.breaks[count] = mPrimitives.get(idx).location; - breakInfo.widths[count] = opt[idx].mWidth; - breakInfo.flags [count] = opt[idx].mHasTabs ? TAB_MASK : 0; - idx = opt[idx].mPrev; - } - } - - private static void resize(LineBreaks lineBreaks, int size) { - if (lineBreaks.breaks.length == size) { - return; - } - int[] breaks = new int[size]; - float[] widths = new float[size]; - int[] flags = new int[size]; - - int toCopy = Math.min(size, lineBreaks.breaks.length); - System.arraycopy(lineBreaks.breaks, 0, breaks, 0, toCopy); - System.arraycopy(lineBreaks.widths, 0, widths, 0, toCopy); - System.arraycopy(lineBreaks.flags, 0, flags, 0, toCopy); - - lineBreaks.breaks = breaks; - lineBreaks.widths = widths; - lineBreaks.flags = flags; - } - - @NonNull - private LineMetrics computeMetrics(int start, int end) { - boolean f = false; - float w = 0, pw = 0; - for (int i = start; i < end; i++) { - Primitive p = mPrimitives.get(i); - if (p.type == PrimitiveType.BOX || p.type == PrimitiveType.GLUE) { - w += p.width; - if (p.type == PrimitiveType.BOX) { - pw = w; - } - } else if (p.type == PrimitiveType.VARIABLE) { - w = mTabStops.width(w); - f = true; - } - } - return new LineMetrics(w, pw, f); - } - - private static float computeDemerits(float maxWidth, float width, boolean finalBreak, - float penalty) { - float deviation = finalBreak ? 0 : maxWidth - width; - return (deviation * deviation) + penalty; - } - - /** - * @return the last break position or -1 if failed. - */ - @SuppressWarnings("ConstantConditions") // method too complex to be analyzed. - private int desperateBreak(int start, int limit, float maxWidth, - @NonNull LineMetrics lineMetrics) { - float w = 0, pw = 0; - boolean breakFound = false; - int breakIndex = 0, firstTabIndex = Integer.MAX_VALUE; - for (int i = start; i < limit; i++) { - Primitive p = mPrimitives.get(i); - - if (p.type == PrimitiveType.BOX || p.type == PrimitiveType.GLUE) { - w += p.width; - if (p.type == PrimitiveType.BOX) { - pw = w; - } - } else if (p.type == PrimitiveType.VARIABLE) { - w = mTabStops.width(w); - firstTabIndex = Math.min(firstTabIndex, i); - } - - if (pw > maxWidth && breakFound) { - break; - } - - // must make progress - if (i > start && - (p.type == PrimitiveType.PENALTY || p.type == PrimitiveType.WORD_BREAK)) { - breakFound = true; - breakIndex = i; - } - } - - if (breakFound) { - lineMetrics.mWidth = w; - lineMetrics.mPrintedWidth = pw; - lineMetrics.mHasTabs = (start <= firstTabIndex && firstTabIndex < breakIndex); - return breakIndex; - } else { - return -1; - } - } - - private static class LineMetrics { - /** Actual width of the line. */ - float mWidth; - /** Width of the line minus trailing whitespace. */ - float mPrintedWidth; - boolean mHasTabs; - - public LineMetrics() { - } - - public LineMetrics(float width, float printedWidth, boolean hasTabs) { - mWidth = width; - mPrintedWidth = printedWidth; - mHasTabs = hasTabs; - } - } - - /** - * A struct to store the info about a break. - */ - @SuppressWarnings("SpellCheckingInspection") // For the word struct. - private static class Node { - // -1 for the first node. - int mPrev; - // number of breaks so far. - int mPrevCount; - float mDemerits; - float mWidth; - boolean mHasTabs; - - public Node(int prev, int prevCount, float demerits, float width, boolean hasTabs) { - mPrev = prev; - mPrevCount = prevCount; - mDemerits = demerits; - mWidth = width; - mHasTabs = hasTabs; - } - } -} diff --git a/tools/layoutlib/bridge/src/android/text/Primitive.java b/tools/layoutlib/bridge/src/android/text/Primitive.java deleted file mode 100644 index 37ed072f2ec1..000000000000 --- a/tools/layoutlib/bridge/src/android/text/Primitive.java +++ /dev/null @@ -1,92 +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.text; - -import android.annotation.NonNull; - -// Based on the native implementation of Primitive in -// frameworks/base/core/jni/android_text_StaticLayout.cpp revision b808260 -public class Primitive { - public final @NonNull PrimitiveType type; - public final int location; - // The following fields don't make sense for all types. - // Box and Glue have width only. - // Penalty has both width and penalty. - // Word_break has penalty only. - public final float width; - public final float penalty; - - /** - * Use {@code PrimitiveType#getNewPrimitive()} - */ - private Primitive(@NonNull PrimitiveType type, int location, float width, float penalty) { - this.type = type; - this.location = location; - this.width = width; - this.penalty = penalty; - } - - public static enum PrimitiveType { - /** - * Something with a constant width that is to be typeset - like a character. - */ - BOX, - /** - * Blank space with fixed width. - */ - GLUE, - /** - * Aesthetic cost indicating how desirable breaking at this point will be. A penalty of - * {@link #PENALTY_INFINITY} means a forced non-break, whereas a penalty of negative - * {@code #PENALTY_INFINITY} means a forced break. - * <p/> - * Currently, it only stores penalty with values 0 or -infinity. - */ - PENALTY, - /** - * For tabs - variable width space. - */ - VARIABLE, - /** - * Possible breakpoints within a word. Think of this as a high cost {@link #PENALTY}. - */ - WORD_BREAK; - - public Primitive getNewPrimitive(int location) { - assert this == VARIABLE; - return new Primitive(this, location, 0f, 0f); - } - - public Primitive getNewPrimitive(int location, float value) { - assert this == BOX || this == GLUE || this == WORD_BREAK; - if (this == BOX || this == GLUE) { - return new Primitive(this, location, value, 0f); - } else { - return new Primitive(this, location, 0f, value); - } - } - - public Primitive getNewPrimitive(int location, float width, float penalty) { - assert this == PENALTY; - return new Primitive(this, location, width, penalty); - } - - // forced non-break, negative infinity is forced break. - public static final float PENALTY_INFINITY = 1e7f; - } -} - diff --git a/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java b/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java deleted file mode 100644 index cc031439226b..000000000000 --- a/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java +++ /dev/null @@ -1,238 +0,0 @@ -package android.text; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.annotation.NonNull; -import android.graphics.BidiRenderer; -import android.graphics.Paint; -import android.graphics.Paint_Delegate; -import android.graphics.RectF; -import android.icu.text.BreakIterator; -import android.icu.util.ULocale; -import android.text.Primitive.PrimitiveType; -import android.text.StaticLayout.LineBreaks; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import javax.swing.text.Segment; - -/** - * Delegate that provides implementation for native 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 StaticLayout_Delegate { - - private static final char CHAR_SPACE = 0x20; - private static final char CHAR_TAB = 0x09; - private static final char CHAR_NEWLINE = 0x0A; - private static final char CHAR_ZWSP = 0x200B; // Zero width space. - - // ---- Builder delegate manager ---- - private static final DelegateManager<Builder> sBuilderManager = - new DelegateManager<Builder>(Builder.class); - - @LayoutlibDelegate - /*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(ByteBuffer buf, int offset, int minPrefix, - int minSuffix) { - return Hyphenator_Delegate.loadHyphenator(buf, offset, minPrefix, minSuffix); - } - - @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, boolean isJustified) { - // TODO: implement justified alignment - Builder builder = sBuilderManager.getDelegate(nativeBuilder); - if (builder == null) { - return; - } - - builder.mText = text; - builder.mWidths = new float[length]; - builder.mLineWidth = new LineWidth(firstWidth, firstWidthLineCount, restWidth); - builder.mTabStopCalculator = new TabStops(variableTabStops, defaultTabStop); - } - - @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); - } - } - - @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; - } - - // compute all possible breakpoints. - int length = builder.mWidths.length; - 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; - it.first(); - while ((loc = it.next()) != BreakIterator.DONE) { - breaks.add(loc); - } - - List<Primitive> primitives = - computePrimitives(builder.mText, builder.mWidths, length, breaks); - switch (builder.mBreakStrategy) { - case Layout.BREAK_STRATEGY_SIMPLE: - builder.mLineBreaker = new GreedyLineBreaker(primitives, builder.mLineWidth, - builder.mTabStopCalculator); - break; - case Layout.BREAK_STRATEGY_HIGH_QUALITY: - // TODO -// break; - case Layout.BREAK_STRATEGY_BALANCED: - builder.mLineBreaker = new OptimizingLineBreaker(primitives, builder.mLineWidth, - builder.mTabStopCalculator); - break; - default: - assert false : "Unknown break strategy: " + builder.mBreakStrategy; - builder.mLineBreaker = new GreedyLineBreaker(primitives, builder.mLineWidth, - builder.mTabStopCalculator); - } - builder.mLineBreaker.computeBreaks(recycle); - return recycle.breaks.length; - } - - /** - * Compute metadata each character - things which help in deciding if it's possible to break - * at a point or not. - */ - @NonNull - private static List<Primitive> computePrimitives(@NonNull char[] text, @NonNull float[] widths, - int length, @NonNull List<Integer> breaks) { - // Initialize the list with a guess of the number of primitives: - // 2 Primitives per non-whitespace char and approx 5 chars per word (i.e. 83% chars) - List<Primitive> primitives = new ArrayList<Primitive>(((int) Math.ceil(length * 1.833))); - int breaksSize = breaks.size(); - int breakIndex = 0; - for (int i = 0; i < length; i++) { - char c = text[i]; - if (c == CHAR_SPACE || c == CHAR_ZWSP) { - primitives.add(PrimitiveType.GLUE.getNewPrimitive(i, widths[i])); - } else if (c == CHAR_TAB) { - primitives.add(PrimitiveType.VARIABLE.getNewPrimitive(i)); - } else if (c != CHAR_NEWLINE) { - while (breakIndex < breaksSize && breaks.get(breakIndex) < i) { - breakIndex++; - } - Primitive p; - if (widths[i] != 0) { - if (breakIndex < breaksSize && breaks.get(breakIndex) == i) { - p = PrimitiveType.PENALTY.getNewPrimitive(i, 0, 0); - } else { - p = PrimitiveType.WORD_BREAK.getNewPrimitive(i, 0); - } - primitives.add(p); - } - - primitives.add(PrimitiveType.BOX.getNewPrimitive(i, widths[i])); - } - } - // final break at end of everything - primitives.add( - PrimitiveType.PENALTY.getNewPrimitive(length, 0, -PrimitiveType.PENALTY_INFINITY)); - return primitives; - } - - private static float measureText(long nativePaint, char []text, int index, int count, - float[] widths, int bidiFlags) { - Paint_Delegate paint = Paint_Delegate.getDelegate(nativePaint); - RectF bounds = new BidiRenderer(null, paint, text) - .renderText(index, index + count, bidiFlags, widths, 0, false); - return bounds.right - bounds.left; - } - - // TODO: Rename to LineBreakerRef and move everything other than LineBreaker to LineBreaker. - /** - * Java representation of the native Builder class. - */ - private static class Builder { - String mLocale; - char[] mText; - float[] mWidths; - LineBreaker mLineBreaker; - long mNativeHyphenator; - int mBreakStrategy; - LineWidth mLineWidth; - TabStops mTabStopCalculator; - } -} diff --git a/tools/layoutlib/bridge/src/android/text/TabStops.java b/tools/layoutlib/bridge/src/android/text/TabStops.java deleted file mode 100644 index 6c2f1e1ff00b..000000000000 --- a/tools/layoutlib/bridge/src/android/text/TabStops.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.text; - -import android.annotation.Nullable; - -// Based on the native implementation of TabStops in -// frameworks/base/core/jni/android_text_StaticLayout.cpp revision b808260 -public class TabStops { - @Nullable - private int[] mStops; - private final int mTabWidth; - - public TabStops(@Nullable int[] stops, int defaultTabWidth) { - mTabWidth = defaultTabWidth; - mStops = stops; - } - - public float width(float widthSoFar) { - if (mStops != null) { - for (int i : mStops) { - if (i > widthSoFar) { - return i; - } - } - } - // find the next tabStop after widthSoFar. - return (int) ((widthSoFar + mTabWidth) / mTabWidth) * mTabWidth; - } -} diff --git a/tools/layoutlib/bridge/src/android/text/format/DateFormat_Delegate.java b/tools/layoutlib/bridge/src/android/text/format/DateFormat_Delegate.java deleted file mode 100644 index 1e4f213597e5..000000000000 --- a/tools/layoutlib/bridge/src/android/text/format/DateFormat_Delegate.java +++ /dev/null @@ -1,42 +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 android.text.format; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.content.Context; - - -/** - * Delegate used to provide new implementation for the native methods of {@link DateFormat} - * - * Through the layoutlib_create tool, the original methods of DateFormat have been replaced - * by calls to methods of the same name in this delegate class. - * - */ -public class DateFormat_Delegate { - - @LayoutlibDelegate - /*package*/ static boolean is24HourFormat(Context context) { - return false; - } - - @LayoutlibDelegate - /*package*/ static boolean is24HourFormat(Context context, int userHandle) { - return false; - } -} diff --git a/tools/layoutlib/bridge/src/android/util/BridgeXmlPullAttributes.java b/tools/layoutlib/bridge/src/android/util/BridgeXmlPullAttributes.java deleted file mode 100644 index 9fd1e1557537..000000000000 --- a/tools/layoutlib/bridge/src/android/util/BridgeXmlPullAttributes.java +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.util; - -import com.android.ide.common.rendering.api.AttrResourceValue; -import com.android.ide.common.rendering.api.RenderResources; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.internal.util.XmlUtils; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.BridgeConstants; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.impl.ResourceHelper; -import com.android.resources.ResourceType; - -import org.xmlpull.v1.XmlPullParser; - -import android.annotation.NonNull; - -import java.util.Map; -import java.util.function.Function; - -/** - * A correct implementation of the {@link AttributeSet} interface on top of a XmlPullParser - */ -public class BridgeXmlPullAttributes extends XmlPullAttributes { - - private final BridgeContext mContext; - private final boolean mPlatformFile; - private final Function<String, Map<String, Integer>> mFrameworkEnumValueSupplier; - private final Function<String, Map<String, Integer>> mProjectEnumValueSupplier; - - // VisibleForTesting - BridgeXmlPullAttributes(@NonNull XmlPullParser parser, @NonNull BridgeContext context, - boolean platformFile, - @NonNull Function<String, Map<String, Integer>> frameworkEnumValueSupplier, - @NonNull Function<String, Map<String, Integer>> projectEnumValueSupplier) { - super(parser); - mContext = context; - mPlatformFile = platformFile; - mFrameworkEnumValueSupplier = frameworkEnumValueSupplier; - mProjectEnumValueSupplier = projectEnumValueSupplier; - } - - public BridgeXmlPullAttributes(@NonNull XmlPullParser parser, @NonNull BridgeContext context, - boolean platformFile) { - this(parser, context, platformFile, Bridge::getEnumValues, attrName -> { - // get the styleable matching the resolved name - RenderResources res = context.getRenderResources(); - ResourceValue attr = res.getProjectResource(ResourceType.ATTR, attrName); - return attr instanceof AttrResourceValue ? - ((AttrResourceValue) attr).getAttributeValues() : null; - }); - } - - /* - * (non-Javadoc) - * @see android.util.XmlPullAttributes#getAttributeNameResource(int) - * - * This methods must return com.android.internal.R.attr.<name> matching - * the name of the attribute. - * It returns 0 if it doesn't find anything. - */ - @Override - public int getAttributeNameResource(int index) { - // get the attribute name. - String name = getAttributeName(index); - - // get the attribute namespace - String ns = mParser.getAttributeNamespace(index); - - if (BridgeConstants.NS_RESOURCES.equals(ns)) { - return Bridge.getResourceId(ResourceType.ATTR, name); - - } - - // this is not an attribute in the android namespace, we query the customviewloader, if - // the namespaces match. - if (mContext.getLayoutlibCallback().getNamespace().equals(ns)) { - Integer v = mContext.getLayoutlibCallback().getResourceId(ResourceType.ATTR, name); - if (v != null) { - return v; - } - } - - return 0; - } - - @Override - public int getAttributeListValue(String namespace, String attribute, - String[] options, int defaultValue) { - String value = getAttributeValue(namespace, attribute); - if (value != null) { - ResourceValue r = getResourceValue(value); - - if (r != null) { - value = r.getValue(); - } - - return XmlUtils.convertValueToList(value, options, defaultValue); - } - - return defaultValue; - } - - @Override - public boolean getAttributeBooleanValue(String namespace, String attribute, - boolean defaultValue) { - String value = getAttributeValue(namespace, attribute); - if (value != null) { - ResourceValue r = getResourceValue(value); - - if (r != null) { - value = r.getValue(); - } - - return XmlUtils.convertValueToBoolean(value, defaultValue); - } - - return defaultValue; - } - - @Override - public int getAttributeResourceValue(String namespace, String attribute, int defaultValue) { - String value = getAttributeValue(namespace, attribute); - - return resolveResourceValue(value, defaultValue); - } - - @Override - public int getAttributeIntValue(String namespace, String attribute, int defaultValue) { - String value = getAttributeValue(namespace, attribute); - if (value == null) { - return defaultValue; - } - - ResourceValue r = getResourceValue(value); - - if (r != null) { - value = r.getValue(); - } - - if (value.charAt(0) == '#') { - return ResourceHelper.getColor(value); - } - - try { - return XmlUtils.convertValueToInt(value, defaultValue); - } catch (NumberFormatException e) { - // This is probably an enum - Map<String, Integer> enumValues = BridgeConstants.NS_RESOURCES.equals(namespace) ? - mFrameworkEnumValueSupplier.apply(attribute) : - mProjectEnumValueSupplier.apply(attribute); - - Integer enumValue = enumValues != null ? enumValues.get(value) : null; - if (enumValue != null) { - return enumValue; - } - - // We weren't able to find the enum int value - throw e; - } - } - - @Override - public int getAttributeUnsignedIntValue(String namespace, String attribute, - int defaultValue) { - String value = getAttributeValue(namespace, attribute); - if (value != null) { - ResourceValue r = getResourceValue(value); - - if (r != null) { - value = r.getValue(); - } - - return XmlUtils.convertValueToUnsignedInt(value, defaultValue); - } - - return defaultValue; - } - - @Override - public float getAttributeFloatValue(String namespace, String attribute, - float defaultValue) { - String s = getAttributeValue(namespace, attribute); - if (s != null) { - ResourceValue r = getResourceValue(s); - - if (r != null) { - s = r.getValue(); - } - - return Float.parseFloat(s); - } - - return defaultValue; - } - - @Override - public int getAttributeListValue(int index, - String[] options, int defaultValue) { - return XmlUtils.convertValueToList( - getAttributeValue(index), options, defaultValue); - } - - @Override - public boolean getAttributeBooleanValue(int index, boolean defaultValue) { - String value = getAttributeValue(index); - if (value != null) { - ResourceValue r = getResourceValue(value); - - if (r != null) { - value = r.getValue(); - } - - return XmlUtils.convertValueToBoolean(value, defaultValue); - } - - return defaultValue; - } - - @Override - public int getAttributeResourceValue(int index, int defaultValue) { - String value = getAttributeValue(index); - - return resolveResourceValue(value, defaultValue); - } - - @Override - public int getAttributeIntValue(int index, int defaultValue) { - return getAttributeIntValue(mParser.getAttributeNamespace(index), - getAttributeName(index) - , defaultValue); - } - - @Override - public int getAttributeUnsignedIntValue(int index, int defaultValue) { - String value = getAttributeValue(index); - if (value != null) { - ResourceValue r = getResourceValue(value); - - if (r != null) { - value = r.getValue(); - } - - return XmlUtils.convertValueToUnsignedInt(value, defaultValue); - } - - return defaultValue; - } - - @Override - public float getAttributeFloatValue(int index, float defaultValue) { - String s = getAttributeValue(index); - if (s != null) { - ResourceValue r = getResourceValue(s); - - if (r != null) { - s = r.getValue(); - } - - return Float.parseFloat(s); - } - - return defaultValue; - } - - // -- private helper methods - - /** - * Returns a resolved {@link ResourceValue} from a given value. - */ - private ResourceValue getResourceValue(String value) { - // now look for this particular value - RenderResources resources = mContext.getRenderResources(); - return resources.resolveResValue(resources.findResValue(value, mPlatformFile)); - } - - /** - * Resolves and return a value to its associated integer. - */ - private int resolveResourceValue(String value, int defaultValue) { - ResourceValue resource = getResourceValue(value); - if (resource != null) { - Integer id = null; - if (mPlatformFile || resource.isFramework()) { - id = Bridge.getResourceId(resource.getResourceType(), resource.getName()); - } else { - id = mContext.getLayoutlibCallback().getResourceId( - resource.getResourceType(), resource.getName()); - } - - if (id != null) { - return id; - } - } - - return defaultValue; - } -} diff --git a/tools/layoutlib/bridge/src/android/util/Log_Delegate.java b/tools/layoutlib/bridge/src/android/util/Log_Delegate.java deleted file mode 100644 index 7f432abdda9f..000000000000 --- a/tools/layoutlib/bridge/src/android/util/Log_Delegate.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2011 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.tools.layoutlib.annotations.LayoutlibDelegate; - -class Log_Delegate { - // to replicate prefix visible when using 'adb logcat' - private static char priorityChar(int priority) { - switch (priority) { - case Log.VERBOSE: - return 'V'; - case Log.DEBUG: - return 'D'; - case Log.INFO: - return 'I'; - case Log.WARN: - return 'W'; - case Log.ERROR: - return 'E'; - case Log.ASSERT: - return 'A'; - default: - return '?'; - } - } - - @LayoutlibDelegate - static int println_native(int bufID, int priority, String tag, String msgs) { - String prefix = priorityChar(priority) + "/" + tag + ": "; - for (String msg: msgs.split("\n")) { - System.out.println(prefix + msg); - } - return 0; - } - -} diff --git a/tools/layoutlib/bridge/src/android/util/LruCache.java b/tools/layoutlib/bridge/src/android/util/LruCache.java deleted file mode 100644 index 520860655abd..000000000000 --- a/tools/layoutlib/bridge/src/android/util/LruCache.java +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Copyright (C) 2011 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 java.util.LinkedHashMap; -import java.util.Map; - -/** - * BEGIN LAYOUTLIB CHANGE - * This is a custom version that doesn't use the non standard LinkedHashMap#eldest. - * END LAYOUTLIB CHANGE - * - * A cache that holds strong references to a limited number of values. Each time - * a value is accessed, it is moved to the head of a queue. When a value is - * added to a full cache, the value at the end of that queue is evicted and may - * become eligible for garbage collection. - * - * <p>If your cached values hold resources that need to be explicitly released, - * override {@link #entryRemoved}. - * - * <p>If a cache miss should be computed on demand for the corresponding keys, - * override {@link #create}. This simplifies the calling code, allowing it to - * assume a value will always be returned, even when there's a cache miss. - * - * <p>By default, the cache size is measured in the number of entries. Override - * {@link #sizeOf} to size the cache in different units. For example, this cache - * is limited to 4MiB of bitmaps: - * <pre> {@code - * int cacheSize = 4 * 1024 * 1024; // 4MiB - * LruCache<String, Bitmap> bitmapCache = new LruCache<String, Bitmap>(cacheSize) { - * protected int sizeOf(String key, Bitmap value) { - * return value.getByteCount(); - * } - * }}</pre> - * - * <p>This class is thread-safe. Perform multiple cache operations atomically by - * synchronizing on the cache: <pre> {@code - * synchronized (cache) { - * if (cache.get(key) == null) { - * cache.put(key, value); - * } - * }}</pre> - * - * <p>This class does not allow null to be used as a key or value. A return - * value of null from {@link #get}, {@link #put} or {@link #remove} is - * unambiguous: the key was not in the cache. - * - * <p>This class appeared in Android 3.1 (Honeycomb MR1); it's available as part - * of <a href="http://developer.android.com/sdk/compatibility-library.html">Android's - * Support Package</a> for earlier releases. - */ -public class LruCache<K, V> { - private final LinkedHashMap<K, V> map; - - /** Size of this cache in units. Not necessarily the number of elements. */ - private int size; - private int maxSize; - - private int putCount; - private int createCount; - private int evictionCount; - private int hitCount; - private int missCount; - - /** - * @param maxSize for caches that do not override {@link #sizeOf}, this is - * the maximum number of entries in the cache. For all other caches, - * this is the maximum sum of the sizes of the entries in this cache. - */ - public LruCache(int maxSize) { - if (maxSize <= 0) { - throw new IllegalArgumentException("maxSize <= 0"); - } - this.maxSize = maxSize; - this.map = new LinkedHashMap<K, V>(0, 0.75f, true); - } - - /** - * Sets the size of the cache. - * @param maxSize The new maximum size. - * - * @hide - */ - public void resize(int maxSize) { - if (maxSize <= 0) { - throw new IllegalArgumentException("maxSize <= 0"); - } - - synchronized (this) { - this.maxSize = maxSize; - } - trimToSize(maxSize); - } - - /** - * Returns the value for {@code key} if it exists in the cache or can be - * created by {@code #create}. If a value was returned, it is moved to the - * head of the queue. This returns null if a value is not cached and cannot - * be created. - */ - public final V get(K key) { - if (key == null) { - throw new NullPointerException("key == null"); - } - - V mapValue; - synchronized (this) { - mapValue = map.get(key); - if (mapValue != null) { - hitCount++; - return mapValue; - } - missCount++; - } - - /* - * Attempt to create a value. This may take a long time, and the map - * may be different when create() returns. If a conflicting value was - * added to the map while create() was working, we leave that value in - * the map and release the created value. - */ - - V createdValue = create(key); - if (createdValue == null) { - return null; - } - - synchronized (this) { - createCount++; - mapValue = map.put(key, createdValue); - - if (mapValue != null) { - // There was a conflict so undo that last put - map.put(key, mapValue); - } else { - size += safeSizeOf(key, createdValue); - } - } - - if (mapValue != null) { - entryRemoved(false, key, createdValue, mapValue); - return mapValue; - } else { - trimToSize(maxSize); - return createdValue; - } - } - - /** - * Caches {@code value} for {@code key}. The value is moved to the head of - * the queue. - * - * @return the previous value mapped by {@code key}. - */ - public final V put(K key, V value) { - if (key == null || value == null) { - throw new NullPointerException("key == null || value == null"); - } - - V previous; - synchronized (this) { - putCount++; - size += safeSizeOf(key, value); - previous = map.put(key, value); - if (previous != null) { - size -= safeSizeOf(key, previous); - } - } - - if (previous != null) { - entryRemoved(false, key, previous, value); - } - - trimToSize(maxSize); - return previous; - } - - /** - * @param maxSize the maximum size of the cache before returning. May be -1 - * to evict even 0-sized elements. - */ - private void trimToSize(int maxSize) { - while (true) { - K key; - V value; - synchronized (this) { - if (size < 0 || (map.isEmpty() && size != 0)) { - throw new IllegalStateException(getClass().getName() - + ".sizeOf() is reporting inconsistent results!"); - } - - if (size <= maxSize) { - break; - } - - // BEGIN LAYOUTLIB CHANGE - // get the last item in the linked list. - // This is not efficient, the goal here is to minimize the changes - // compared to the platform version. - Map.Entry<K, V> toEvict = null; - for (Map.Entry<K, V> entry : map.entrySet()) { - toEvict = entry; - } - // END LAYOUTLIB CHANGE - - if (toEvict == null) { - break; - } - - key = toEvict.getKey(); - value = toEvict.getValue(); - map.remove(key); - size -= safeSizeOf(key, value); - evictionCount++; - } - - entryRemoved(true, key, value, null); - } - } - - /** - * Removes the entry for {@code key} if it exists. - * - * @return the previous value mapped by {@code key}. - */ - public final V remove(K key) { - if (key == null) { - throw new NullPointerException("key == null"); - } - - V previous; - synchronized (this) { - previous = map.remove(key); - if (previous != null) { - size -= safeSizeOf(key, previous); - } - } - - if (previous != null) { - entryRemoved(false, key, previous, null); - } - - return previous; - } - - /** - * Called for entries that have been evicted or removed. This method is - * invoked when a value is evicted to make space, removed by a call to - * {@link #remove}, or replaced by a call to {@link #put}. The default - * implementation does nothing. - * - * <p>The method is called without synchronization: other threads may - * access the cache while this method is executing. - * - * @param evicted true if the entry is being removed to make space, false - * if the removal was caused by a {@link #put} or {@link #remove}. - * @param newValue the new value for {@code key}, if it exists. If non-null, - * this removal was caused by a {@link #put}. Otherwise it was caused by - * an eviction or a {@link #remove}. - */ - protected void entryRemoved(boolean evicted, K key, V oldValue, V newValue) {} - - /** - * Called after a cache miss to compute a value for the corresponding key. - * Returns the computed value or null if no value can be computed. The - * default implementation returns null. - * - * <p>The method is called without synchronization: other threads may - * access the cache while this method is executing. - * - * <p>If a value for {@code key} exists in the cache when this method - * returns, the created value will be released with {@link #entryRemoved} - * and discarded. This can occur when multiple threads request the same key - * at the same time (causing multiple values to be created), or when one - * thread calls {@link #put} while another is creating a value for the same - * key. - */ - protected V create(K key) { - return null; - } - - private int safeSizeOf(K key, V value) { - int result = sizeOf(key, value); - if (result < 0) { - throw new IllegalStateException("Negative size: " + key + "=" + value); - } - return result; - } - - /** - * Returns the size of the entry for {@code key} and {@code value} in - * user-defined units. The default implementation returns 1 so that size - * is the number of entries and max size is the maximum number of entries. - * - * <p>An entry's size must not change while it is in the cache. - */ - protected int sizeOf(K key, V value) { - return 1; - } - - /** - * Clear the cache, calling {@link #entryRemoved} on each removed entry. - */ - public final void evictAll() { - trimToSize(-1); // -1 will evict 0-sized elements - } - - /** - * For caches that do not override {@link #sizeOf}, this returns the number - * of entries in the cache. For all other caches, this returns the sum of - * the sizes of the entries in this cache. - */ - public synchronized final int size() { - return size; - } - - /** - * For caches that do not override {@link #sizeOf}, this returns the maximum - * number of entries in the cache. For all other caches, this returns the - * maximum sum of the sizes of the entries in this cache. - */ - public synchronized final int maxSize() { - return maxSize; - } - - /** - * Returns the number of times {@link #get} returned a value that was - * already present in the cache. - */ - public synchronized final int hitCount() { - return hitCount; - } - - /** - * Returns the number of times {@link #get} returned null or required a new - * value to be created. - */ - public synchronized final int missCount() { - return missCount; - } - - /** - * Returns the number of times {@link #create(Object)} returned a value. - */ - public synchronized final int createCount() { - return createCount; - } - - /** - * Returns the number of times {@link #put} was called. - */ - public synchronized final int putCount() { - return putCount; - } - - /** - * Returns the number of values that have been evicted. - */ - public synchronized final int evictionCount() { - return evictionCount; - } - - /** - * Returns a copy of the current contents of the cache, ordered from least - * recently accessed to most recently accessed. - */ - public synchronized final Map<K, V> snapshot() { - return new LinkedHashMap<K, V>(map); - } - - @Override public synchronized final String toString() { - int accesses = hitCount + missCount; - int hitPercent = accesses != 0 ? (100 * hitCount / accesses) : 0; - return String.format("LruCache[maxSize=%d,hits=%d,misses=%d,hitRate=%d%%]", - maxSize, hitCount, missCount, hitPercent); - } -} diff --git a/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java b/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java deleted file mode 100644 index 7b69388a0b1e..000000000000 --- a/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java +++ /dev/null @@ -1,844 +0,0 @@ -/* - * 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.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; - - public static PathParser_Delegate getDelegate(long nativePtr) { - return sManager.getDelegate(nativePtr); - } - - private PathParser_Delegate(@NonNull PathDataNode[] nodes) { - mPathDataNodes = nodes; - } - - public PathDataNode[] getPathDataNodes() { - return mPathDataNodes; - } - - @LayoutlibDelegate - /*package*/ static void nParseStringForPath(long pathPtr, @NonNull String pathString, int - stringLength) { - Path_Delegate path_delegate = Path_Delegate.getDelegate(pathPtr); - if (path_delegate == null) { - return; - } - assert pathString.length() == stringLength; - PathDataNode.nodesToPath(createNodesFromPathData(pathString), path_delegate); - } - - @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); - } - - @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++) { - if (out.mPathDataNodes[i] == null) { - out.mPathDataNodes[i] = new PathDataNode(from.mPathDataNodes[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) { - PathParser_Delegate fromPath = PathParser_Delegate.getDelegate(fromDataPtr); - PathParser_Delegate toPath = PathParser_Delegate.getDelegate(toDataPtr); - if (fromPath == null || toPath == null || fromPath.getPathDataNodes() == null || toPath - .getPathDataNodes() == null) { - return true; - } - return PathParser_Delegate.canMorph(fromPath.getPathDataNodes(), toPath.getPathDataNodes()); - } - - @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 - public 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 - public 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; - } - - /** - * @param nodesFrom The source path represented in an array of PathDataNode - * @param nodesTo The target path represented in an array of PathDataNode - * @return whether the <code>nodesFrom</code> can morph into <code>nodesTo</code> - */ - public static boolean canMorph(PathDataNode[] nodesFrom, PathDataNode[] nodesTo) { - if (nodesFrom == null || nodesTo == null) { - return false; - } - - if (nodesFrom.length != nodesTo.length) { - return false; - } - - for (int i = 0; i < nodesFrom.length; i ++) { - if (nodesFrom[i].mType != nodesTo[i].mType - || nodesFrom[i].mParams.length != nodesTo[i].mParams.length) { - return false; - } - } - return true; - } - - /** - * Update the target's data to match the source. - * Before calling this, make sure canMorph(target, source) is true. - * - * @param target The target path represented in an array of PathDataNode - * @param source The source path represented in an array of PathDataNode - */ - public static void updateNodes(PathDataNode[] target, PathDataNode[] source) { - for (int i = 0; i < source.length; i ++) { - target[i].mType = source[i].mType; - for (int j = 0; j < source[i].mParams.length; j ++) { - target[i].mParams[j] = source[i].mParams[j]; - } - } - } - - 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) { - assert false : "error in parsing \"" + s + "\"" + e; - return new float[0]; - } - } - - - 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. - */ - public 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. Reset the passed path as needed before - * calling this method. - * - * @param node The source array of PathDataNode. - * @param path The target Path object. - */ - public static void nodesToPath(@NonNull PathDataNode[] node, @NonNull Path_Delegate 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 Path_Delegate path, float[] current, - char previousCmd, char cmd, @NonNull float[] val) { - - int incr = 2; - float currentX = current[0]; - float currentY = current[1]; - float ctrlPointX = current[2]; - float ctrlPointY = current[3]; - float currentSegmentStartX = current[4]; - float currentSegmentStartY = current[5]; - float reflectiveCtrlPointX; - float reflectiveCtrlPointY; - - switch (cmd) { - case 'z': - case 'Z': - path.close(); - // Path is closed here, but we need to move the pen to the - // closed position. So we cache the segment's starting position, - // and restore it here. - currentX = currentSegmentStartX; - currentY = currentSegmentStartY; - ctrlPointX = currentSegmentStartX; - ctrlPointY = currentSegmentStartY; - path.moveTo(currentX, currentY); - break; - 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; - break; - } - - for (int k = 0; k < val.length; k += incr) { - switch (cmd) { - case 'm': // moveto - Start a new sub-path (relative) - currentX += val[k + 0]; - currentY += 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.rLineTo(val[k + 0], val[k + 1]); - } else { - path.rMoveTo(val[k + 0], val[k + 1]); - currentSegmentStartX = currentX; - currentSegmentStartY = currentY; - } - break; - case 'M': // moveto - Start a new sub-path - currentX = val[k + 0]; - currentY = 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(val[k + 0], val[k + 1]); - } else { - path.moveTo(val[k + 0], val[k + 1]); - currentSegmentStartX = currentX; - currentSegmentStartY = currentY; - } - break; - case 'l': // lineto - Draw a line from the current point (relative) - path.rLineTo(val[k + 0], val[k + 1]); - currentX += val[k + 0]; - currentY += val[k + 1]; - break; - case 'L': // lineto - Draw a line from the current point - path.lineTo(val[k + 0], val[k + 1]); - currentX = val[k + 0]; - currentY = val[k + 1]; - break; - case 'h': // horizontal lineto - Draws a horizontal line (relative) - path.rLineTo(val[k + 0], 0); - currentX += val[k + 0]; - break; - case 'H': // horizontal lineto - Draws a horizontal line - path.lineTo(val[k + 0], currentY); - currentX = val[k + 0]; - break; - case 'v': // vertical lineto - Draws a vertical line from the current point (r) - path.rLineTo(0, val[k + 0]); - currentY += val[k + 0]; - break; - case 'V': // vertical lineto - Draws a vertical line from the current point - path.lineTo(currentX, val[k + 0]); - currentY = val[k + 0]; - break; - case 'c': // curveto - Draws a cubic Bézier curve (relative) - path.rCubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3], - val[k + 4], val[k + 5]); - - ctrlPointX = currentX + val[k + 2]; - ctrlPointY = currentY + val[k + 3]; - currentX += val[k + 4]; - currentY += val[k + 5]; - - break; - case 'C': // curveto - Draws a cubic Bézier curve - path.cubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3], - val[k + 4], val[k + 5]); - currentX = val[k + 4]; - currentY = val[k + 5]; - ctrlPointX = val[k + 2]; - ctrlPointY = val[k + 3]; - break; - case 's': // smooth curveto - Draws a cubic Bézier curve (reflective cp) - reflectiveCtrlPointX = 0; - reflectiveCtrlPointY = 0; - if (previousCmd == 'c' || previousCmd == 's' - || previousCmd == 'C' || previousCmd == 'S') { - reflectiveCtrlPointX = currentX - ctrlPointX; - reflectiveCtrlPointY = currentY - ctrlPointY; - } - path.rCubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY, - val[k + 0], val[k + 1], - val[k + 2], val[k + 3]); - - ctrlPointX = currentX + val[k + 0]; - ctrlPointY = currentY + val[k + 1]; - currentX += val[k + 2]; - currentY += val[k + 3]; - break; - case 'S': // shorthand/smooth curveto Draws a cubic Bézier curve(reflective cp) - reflectiveCtrlPointX = currentX; - reflectiveCtrlPointY = currentY; - if (previousCmd == 'c' || previousCmd == 's' - || previousCmd == 'C' || previousCmd == 'S') { - reflectiveCtrlPointX = 2 * currentX - ctrlPointX; - reflectiveCtrlPointY = 2 * currentY - ctrlPointY; - } - path.cubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY, - val[k + 0], val[k + 1], val[k + 2], val[k + 3]); - ctrlPointX = val[k + 0]; - ctrlPointY = val[k + 1]; - currentX = val[k + 2]; - currentY = val[k + 3]; - break; - case 'q': // Draws a quadratic Bézier (relative) - path.rQuadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]); - ctrlPointX = currentX + val[k + 0]; - ctrlPointY = currentY + val[k + 1]; - currentX += val[k + 2]; - currentY += val[k + 3]; - break; - case 'Q': // Draws a quadratic Bézier - path.quadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]); - ctrlPointX = val[k + 0]; - ctrlPointY = val[k + 1]; - currentX = val[k + 2]; - currentY = val[k + 3]; - break; - case 't': // Draws a quadratic Bézier curve(reflective control point)(relative) - reflectiveCtrlPointX = 0; - reflectiveCtrlPointY = 0; - if (previousCmd == 'q' || previousCmd == 't' - || previousCmd == 'Q' || previousCmd == 'T') { - reflectiveCtrlPointX = currentX - ctrlPointX; - reflectiveCtrlPointY = currentY - ctrlPointY; - } - path.rQuadTo(reflectiveCtrlPointX, reflectiveCtrlPointY, - val[k + 0], val[k + 1]); - ctrlPointX = currentX + reflectiveCtrlPointX; - ctrlPointY = currentY + reflectiveCtrlPointY; - currentX += val[k + 0]; - currentY += val[k + 1]; - break; - case 'T': // Draws a quadratic Bézier curve (reflective control point) - reflectiveCtrlPointX = currentX; - reflectiveCtrlPointY = currentY; - if (previousCmd == 'q' || previousCmd == 't' - || previousCmd == 'Q' || previousCmd == 'T') { - reflectiveCtrlPointX = 2 * currentX - ctrlPointX; - reflectiveCtrlPointY = 2 * currentY - ctrlPointY; - } - path.quadTo(reflectiveCtrlPointX, reflectiveCtrlPointY, - val[k + 0], val[k + 1]); - ctrlPointX = reflectiveCtrlPointX; - ctrlPointY = reflectiveCtrlPointY; - currentX = val[k + 0]; - currentY = val[k + 1]; - break; - case 'a': // Draws an elliptical arc - // (rx ry x-axis-rotation large-arc-flag sweep-flag x y) - drawArc(path, - currentX, - currentY, - val[k + 5] + currentX, - val[k + 6] + currentY, - val[k + 0], - val[k + 1], - val[k + 2], - val[k + 3] != 0, - val[k + 4] != 0); - currentX += val[k + 5]; - currentY += val[k + 6]; - ctrlPointX = currentX; - ctrlPointY = currentY; - break; - case 'A': // Draws an elliptical arc - drawArc(path, - currentX, - currentY, - val[k + 5], - val[k + 6], - val[k + 0], - val[k + 1], - val[k + 2], - val[k + 3] != 0, - val[k + 4] != 0); - currentX = val[k + 5]; - currentY = val[k + 6]; - ctrlPointX = currentX; - ctrlPointY = currentY; - break; - } - previousCmd = cmd; - } - current[0] = currentX; - current[1] = currentY; - current[2] = ctrlPointX; - current[3] = ctrlPointY; - current[4] = currentSegmentStartX; - current[5] = currentSegmentStartY; - } - - private static void drawArc(@NonNull Path_Delegate 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 Path_Delegate 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.cubicTo((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/util/Xml_Delegate.java b/tools/layoutlib/bridge/src/android/util/Xml_Delegate.java deleted file mode 100644 index 213e848659bf..000000000000 --- a/tools/layoutlib/bridge/src/android/util/Xml_Delegate.java +++ /dev/null @@ -1,45 +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.util; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.layoutlib.bridge.impl.ParserFactory; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -/** - * Delegate overriding some methods of android.util.Xml - * - * Through the layoutlib_create tool, the original methods of Xml have been replaced - * by calls to methods of the same name in this delegate class. - * - * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager} - * around to map int to instance of the delegate. - */ -public class Xml_Delegate { - - @LayoutlibDelegate - /*package*/ static XmlPullParser newPullParser() { - try { - return ParserFactory.instantiateParser(null); - } catch (XmlPullParserException e) { - throw new AssertionError(); - } - } -} diff --git a/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java b/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java deleted file mode 100644 index 4445a2238538..000000000000 --- a/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2011 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.view; - -import com.android.layoutlib.bridge.android.BridgeWindow; -import com.android.layoutlib.bridge.android.BridgeWindowSession; - -import android.content.Context; -import android.os.Handler; -import android.view.View.AttachInfo; - -/** - * Class allowing access to package-protected methods/fields. - */ -public class AttachInfo_Accessor { - - public static void setAttachInfo(View view) { - Context context = view.getContext(); - WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); - Display display = wm.getDefaultDisplay(); - ViewRootImpl root = new ViewRootImpl(context, display); - AttachInfo info = new AttachInfo(new BridgeWindowSession(), new BridgeWindow(), - display, root, new Handler(), null, context); - info.mHasWindowFocus = true; - info.mWindowVisibility = View.VISIBLE; - info.mInTouchMode = false; // this is so that we can display selections. - info.mHardwareAccelerated = false; - view.dispatchAttachedToWindow(info, 0); - } - - public static void dispatchOnPreDraw(View view) { - view.mAttachInfo.mTreeObserver.dispatchOnPreDraw(); - } - - public static void detachFromWindow(View view) { - if (view != null) { - view.dispatchDetachedFromWindow(); - } - } - - public static ViewRootImpl getRootView(View view) { - return view.mAttachInfo != null ? view.mAttachInfo.mViewRootImpl : null; - } -} diff --git a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java deleted file mode 100644 index b6e6ec008449..000000000000 --- a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java +++ /dev/null @@ -1,496 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.view; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.ide.common.rendering.api.LayoutlibCallback; -import com.android.ide.common.rendering.api.MergeCookie; -import com.android.ide.common.rendering.api.ResourceReference; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.BridgeConstants; -import com.android.layoutlib.bridge.MockView; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; -import com.android.layoutlib.bridge.android.support.DrawerLayoutUtil; -import com.android.layoutlib.bridge.android.support.RecyclerViewUtil; -import com.android.layoutlib.bridge.impl.ParserFactory; -import com.android.layoutlib.bridge.util.ReflectionUtils; -import com.android.resources.ResourceType; -import com.android.util.Pair; - -import org.xmlpull.v1.XmlPullParser; - -import android.annotation.NonNull; -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.drawable.Animatable; -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; -import android.widget.ImageView; -import android.widget.NumberPicker; - -import java.io.File; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import static com.android.SdkConstants.AUTO_COMPLETE_TEXT_VIEW; -import static com.android.SdkConstants.BUTTON; -import static com.android.SdkConstants.CHECKED_TEXT_VIEW; -import static com.android.SdkConstants.CHECK_BOX; -import static com.android.SdkConstants.EDIT_TEXT; -import static com.android.SdkConstants.IMAGE_BUTTON; -import static com.android.SdkConstants.IMAGE_VIEW; -import static com.android.SdkConstants.MULTI_AUTO_COMPLETE_TEXT_VIEW; -import static com.android.SdkConstants.RADIO_BUTTON; -import static com.android.SdkConstants.SEEK_BAR; -import static com.android.SdkConstants.SPINNER; -import static com.android.SdkConstants.TEXT_VIEW; -import static com.android.layoutlib.bridge.android.BridgeContext.getBaseContext; - -/** - * Custom implementation of {@link LayoutInflater} to handle custom views. - */ -public final class BridgeInflater extends LayoutInflater { - - private final LayoutlibCallback mLayoutlibCallback; - /** - * If true, the inflater will try to replace the framework widgets with the AppCompat versions. - * Ideally, this should be based on the activity being an AppCompat activity but since that is - * not trivial to check from layoutlib, we currently base the decision on the current theme - * being an AppCompat theme. - */ - private boolean mLoadAppCompatViews; - /** - * This set contains the framework views that have an AppCompat version but failed to load. - * This might happen because not all widgets are contained in all versions of the support - * library. - * This will help us to avoid trying to load the AppCompat version multiple times if it - * doesn't exist. - */ - private Set<String> mFailedAppCompatViews = new HashSet<>(); - private boolean mIsInMerge = false; - private ResourceReference mResourceReference; - private Map<View, String> mOpenDrawerLayouts; - - // Keep in sync with the same value in LayoutInflater. - private static final int[] ATTRS_THEME = new int[] {com.android.internal.R.attr.theme }; - - private static final String APPCOMPAT_WIDGET_PREFIX = "android.support.v7.widget.AppCompat"; - /** List of platform widgets that have an AppCompat version */ - private static final Set<String> APPCOMPAT_VIEWS = Collections.unmodifiableSet( - new HashSet<>( - Arrays.asList(TEXT_VIEW, IMAGE_VIEW, BUTTON, EDIT_TEXT, SPINNER, - IMAGE_BUTTON, CHECK_BOX, RADIO_BUTTON, CHECKED_TEXT_VIEW, - AUTO_COMPLETE_TEXT_VIEW, MULTI_AUTO_COMPLETE_TEXT_VIEW, "RatingBar", - SEEK_BAR))); - - /** - * List of class prefixes which are tried first by default. - * <p/> - * This should match the list in com.android.internal.policy.impl.PhoneLayoutInflater. - */ - private static final String[] sClassPrefixList = { - "android.widget.", - "android.webkit.", - "android.app." - }; - - public static String[] getClassPrefixList() { - return sClassPrefixList; - } - - private BridgeInflater(LayoutInflater original, Context newContext) { - super(original, newContext); - newContext = getBaseContext(newContext); - if (newContext instanceof BridgeContext) { - mLayoutlibCallback = ((BridgeContext) newContext).getLayoutlibCallback(); - mLoadAppCompatViews = ((BridgeContext) newContext).isAppCompatTheme(); - } else { - mLayoutlibCallback = null; - mLoadAppCompatViews = false; - } - } - - /** - * Instantiate a new BridgeInflater with an {@link LayoutlibCallback} object. - * - * @param context The Android application context. - * @param layoutlibCallback the {@link LayoutlibCallback} object. - */ - public BridgeInflater(BridgeContext context, LayoutlibCallback layoutlibCallback) { - super(context); - mLayoutlibCallback = layoutlibCallback; - mConstructorArgs[0] = context; - mLoadAppCompatViews = context.isAppCompatTheme(); - } - - @Override - public View onCreateView(String name, AttributeSet attrs) throws ClassNotFoundException { - View view = null; - - try { - if (mLoadAppCompatViews - && APPCOMPAT_VIEWS.contains(name) - && !mFailedAppCompatViews.contains(name)) { - // We are using an AppCompat theme so try to load the appcompat views - view = loadCustomView(APPCOMPAT_WIDGET_PREFIX + name, attrs, true); - - if (view == null) { - mFailedAppCompatViews.add(name); // Do not try this one anymore - } - } - - if (view == null) { - // First try to find a class using the default Android prefixes - for (String prefix : sClassPrefixList) { - try { - view = createView(name, prefix, attrs); - if (view != null) { - break; - } - } catch (ClassNotFoundException e) { - // Ignore. We'll try again using the base class below. - } - } - - // Next try using the parent loader. This will most likely only work for - // fully-qualified class names. - try { - if (view == null) { - view = super.onCreateView(name, attrs); - } - } catch (ClassNotFoundException e) { - // Ignore. We'll try again using the custom view loader below. - } - } - - // Finally try again using the custom view loader - if (view == null) { - view = loadCustomView(name, attrs); - } - } catch (InflateException e) { - // Don't catch the InflateException below as that results in hiding the real cause. - throw e; - } catch (Exception e) { - // Wrap the real exception in a ClassNotFoundException, so that the calling method - // can deal with it. - throw new ClassNotFoundException("onCreateView", e); - } - - setupViewInContext(view, attrs); - - return view; - } - - @Override - public View createViewFromTag(View parent, String name, Context context, AttributeSet attrs, - boolean ignoreThemeAttr) { - View view = null; - if (name.equals("view")) { - // This is usually done by the superclass but this allows us catching the error and - // reporting something useful. - name = attrs.getAttributeValue(null, "class"); - - if (name == null) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, "Unable to inflate view tag without " + - "class attribute", null); - // We weren't able to resolve the view so we just pass a mock View to be able to - // continue rendering. - view = new MockView(context, attrs); - ((MockView) view).setText("view"); - } - } - - try { - if (view == null) { - view = super.createViewFromTag(parent, name, context, attrs, ignoreThemeAttr); - } - } catch (InflateException e) { - // Creation of ContextThemeWrapper code is same as in the super method. - // Apply a theme wrapper, if allowed and one is specified. - if (!ignoreThemeAttr) { - final TypedArray ta = context.obtainStyledAttributes(attrs, ATTRS_THEME); - final int themeResId = ta.getResourceId(0, 0); - if (themeResId != 0) { - context = new ContextThemeWrapper(context, themeResId); - } - ta.recycle(); - } - if (!(e.getCause() instanceof ClassNotFoundException)) { - // There is some unknown inflation exception in inflating a View that was found. - view = new MockView(context, attrs); - ((MockView) view).setText(name); - Bridge.getLog().error(LayoutLog.TAG_BROKEN, e.getMessage(), e, null); - } else { - final Object lastContext = mConstructorArgs[0]; - mConstructorArgs[0] = context; - // try to load the class from using the custom view loader - try { - view = loadCustomView(name, attrs); - } catch (Exception e2) { - // Wrap the real exception in an InflateException so that the calling - // method can deal with it. - InflateException exception = new InflateException(); - if (!e2.getClass().equals(ClassNotFoundException.class)) { - exception.initCause(e2); - } else { - exception.initCause(e); - } - throw exception; - } finally { - mConstructorArgs[0] = lastContext; - } - } - } - - setupViewInContext(view, attrs); - - return view; - } - - @Override - public View inflate(int resource, ViewGroup root) { - Context context = getContext(); - context = getBaseContext(context); - if (context instanceof BridgeContext) { - BridgeContext bridgeContext = (BridgeContext)context; - - ResourceValue value = null; - - @SuppressWarnings("deprecation") - Pair<ResourceType, String> layoutInfo = Bridge.resolveResourceId(resource); - if (layoutInfo != null) { - value = bridgeContext.getRenderResources().getFrameworkResource( - ResourceType.LAYOUT, layoutInfo.getSecond()); - } else { - layoutInfo = mLayoutlibCallback.resolveResourceId(resource); - - if (layoutInfo != null) { - value = bridgeContext.getRenderResources().getProjectResource( - ResourceType.LAYOUT, layoutInfo.getSecond()); - } - } - - if (value != null) { - File f = new File(value.getValue()); - if (f.isFile()) { - try { - XmlPullParser parser = ParserFactory.create(f, true); - - BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser( - parser, bridgeContext, value.isFramework()); - - return inflate(bridgeParser, root); - } catch (Exception e) { - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ, - "Failed to parse file " + f.getAbsolutePath(), e, null); - - return null; - } - } - } - } - return null; - } - - /** - * Instantiates the given view name and returns the instance. If the view doesn't exist, a - * MockView or null might be returned. - * @param name the custom view name - * @param attrs the {@link AttributeSet} to be passed to the view constructor - * @param silent if true, errors while loading the view won't be reported and, if the view - * doesn't exist, null will be returned. - */ - private View loadCustomView(String name, AttributeSet attrs, boolean silent) throws Exception { - if (mLayoutlibCallback != null) { - // first get the classname in case it's not the node name - if (name.equals("view")) { - name = attrs.getAttributeValue(null, "class"); - if (name == null) { - return null; - } - } - - mConstructorArgs[1] = attrs; - - Object customView = silent ? - mLayoutlibCallback.loadClass(name, mConstructorSignature, mConstructorArgs) - : mLayoutlibCallback.loadView(name, mConstructorSignature, mConstructorArgs); - - if (customView instanceof View) { - return (View)customView; - } - } - - return null; - } - - private View loadCustomView(String name, AttributeSet attrs) throws Exception { - return loadCustomView(name, attrs, false); - } - - private void setupViewInContext(View view, AttributeSet attrs) { - Context context = getContext(); - context = getBaseContext(context); - if (context instanceof BridgeContext) { - BridgeContext bc = (BridgeContext) context; - // get the view key - Object viewKey = getViewKeyFromParser(attrs, bc, mResourceReference, mIsInMerge); - if (viewKey != null) { - bc.addViewKey(view, viewKey); - } - String scrollPosX = attrs.getAttributeValue(BridgeConstants.NS_RESOURCES, "scrollX"); - if (scrollPosX != null && scrollPosX.endsWith("px")) { - int value = Integer.parseInt(scrollPosX.substring(0, scrollPosX.length() - 2)); - bc.setScrollXPos(view, value); - } - String scrollPosY = attrs.getAttributeValue(BridgeConstants.NS_RESOURCES, "scrollY"); - if (scrollPosY != null && scrollPosY.endsWith("px")) { - int value = Integer.parseInt(scrollPosY.substring(0, scrollPosY.length() - 2)); - bc.setScrollYPos(view, value); - } - if (ReflectionUtils.isInstanceOf(view, RecyclerViewUtil.CN_RECYCLER_VIEW)) { - Integer resourceId = null; - String attrVal = attrs.getAttributeValue(BridgeConstants.NS_TOOLS_URI, - BridgeConstants.ATTR_LIST_ITEM); - if (attrVal != null && !attrVal.isEmpty()) { - ResourceValue resValue = bc.getRenderResources().findResValue(attrVal, false); - if (resValue.isFramework()) { - resourceId = Bridge.getResourceId(resValue.getResourceType(), - resValue.getName()); - } else { - resourceId = mLayoutlibCallback.getResourceId(resValue.getResourceType(), - resValue.getName()); - } - } - if (resourceId == null) { - resourceId = 0; - } - RecyclerViewUtil.setAdapter(view, bc, mLayoutlibCallback, resourceId); - } else if (ReflectionUtils.isInstanceOf(view, DrawerLayoutUtil.CN_DRAWER_LAYOUT)) { - String attrVal = attrs.getAttributeValue(BridgeConstants.NS_TOOLS_URI, - BridgeConstants.ATTR_OPEN_DRAWER); - if (attrVal != null) { - getDrawerLayoutMap().put(view, attrVal); - } - } - else if (view instanceof NumberPicker) { - NumberPicker numberPicker = (NumberPicker) view; - String minValue = attrs.getAttributeValue(BridgeConstants.NS_TOOLS_URI, "minValue"); - if (minValue != null) { - numberPicker.setMinValue(Integer.parseInt(minValue)); - } - String maxValue = attrs.getAttributeValue(BridgeConstants.NS_TOOLS_URI, "maxValue"); - if (maxValue != null) { - numberPicker.setMaxValue(Integer.parseInt(maxValue)); - } - } - else if (view instanceof ImageView) { - ImageView img = (ImageView) view; - Drawable drawable = img.getDrawable(); - if (drawable instanceof Animatable) { - if (!((Animatable) drawable).isRunning()) { - ((Animatable) drawable).start(); - } - } - } - - } - } - - public void setIsInMerge(boolean isInMerge) { - mIsInMerge = isInMerge; - } - - public void setResourceReference(ResourceReference reference) { - mResourceReference = reference; - } - - @Override - public LayoutInflater cloneInContext(Context newContext) { - return new BridgeInflater(this, newContext); - } - - /*package*/ static Object getViewKeyFromParser(AttributeSet attrs, BridgeContext bc, - ResourceReference resourceReference, boolean isInMerge) { - - if (!(attrs instanceof BridgeXmlBlockParser)) { - return null; - } - BridgeXmlBlockParser parser = ((BridgeXmlBlockParser) attrs); - - // get the view key - Object viewKey = parser.getViewCookie(); - - if (viewKey == null) { - int currentDepth = parser.getDepth(); - - // test whether we are in an included file or in a adapter binding view. - BridgeXmlBlockParser previousParser = bc.getPreviousParser(); - if (previousParser != null) { - // looks like we are inside an embedded layout. - // only apply the cookie of the calling node (<include>) if we are at the - // top level of the embedded layout. If there is a merge tag, then - // skip it and look for the 2nd level - int testDepth = isInMerge ? 2 : 1; - if (currentDepth == testDepth) { - viewKey = previousParser.getViewCookie(); - // if we are in a merge, wrap the cookie in a MergeCookie. - if (viewKey != null && isInMerge) { - viewKey = new MergeCookie(viewKey); - } - } - } else if (resourceReference != null && currentDepth == 1) { - // else if there's a resource reference, this means we are in an adapter - // binding case. Set the resource ref as the view cookie only for the top - // level view. - viewKey = resourceReference; - } - } - - return viewKey; - } - - public void postInflateProcess(View view) { - if (mOpenDrawerLayouts != null) { - String gravity = mOpenDrawerLayouts.get(view); - if (gravity != null) { - DrawerLayoutUtil.openDrawer(view, gravity); - } - mOpenDrawerLayouts.remove(view); - } - } - - @NonNull - private Map<View, String> getDrawerLayoutMap() { - if (mOpenDrawerLayouts == null) { - mOpenDrawerLayouts = new HashMap<View, String>(4); - } - return mOpenDrawerLayouts; - } - - public void onDoneInflation() { - if (mOpenDrawerLayouts != null) { - mOpenDrawerLayouts.clear(); - } - } -} diff --git a/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java b/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java deleted file mode 100644 index 494ffa1518ab..000000000000 --- a/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2012 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.view; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.layoutlib.bridge.Bridge; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; -import com.android.tools.layoutlib.java.System_Delegate; - -import java.lang.reflect.Field; -import java.util.concurrent.atomic.AtomicReference; - -/** - * Delegate used to provide new implementation of a select few methods of {@link Choreographer} - * - * Through the layoutlib_create tool, the original methods of Choreographer have been - * replaced by calls to methods of the same name in this delegate class. - * - */ -public class Choreographer_Delegate { - static final AtomicReference<Choreographer> mInstance = new AtomicReference<Choreographer>(); - - @LayoutlibDelegate - public static Choreographer getInstance() { - if (mInstance.get() == null) { - mInstance.compareAndSet(null, Choreographer.getInstance_Original()); - } - - return mInstance.get(); - } - - @LayoutlibDelegate - public static float getRefreshRate() { - return 60.f; - } - - @LayoutlibDelegate - static void scheduleVsyncLocked(Choreographer thisChoreographer) { - // do nothing - } - - public static void doFrame(long frameTimeNanos) { - Choreographer thisChoreographer = Choreographer.getInstance(); - - thisChoreographer.mLastFrameTimeNanos = frameTimeNanos - thisChoreographer - .getFrameIntervalNanos(); - thisChoreographer.mFrameInfo.markInputHandlingStart(); - thisChoreographer.doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos); - - thisChoreographer.mFrameInfo.markAnimationsStart(); - thisChoreographer.doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos); - - thisChoreographer.mFrameInfo.markPerformTraversalsStart(); - thisChoreographer.doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos); - - thisChoreographer.doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos); - } - - public static void dispose() { - try { - Field threadInstanceField = Choreographer.class.getDeclaredField("sThreadInstance"); - threadInstanceField.setAccessible(true); - @SuppressWarnings("unchecked") ThreadLocal<Choreographer> threadInstance = - (ThreadLocal<Choreographer>) threadInstanceField.get(null); - threadInstance.remove(); - } catch (ReflectiveOperationException e) { - assert false; - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "Unable to clear Choreographer memory.", e, null); - } - } -} diff --git a/tools/layoutlib/bridge/src/android/view/Display_Delegate.java b/tools/layoutlib/bridge/src/android/view/Display_Delegate.java deleted file mode 100644 index 53dc821f65d2..000000000000 --- a/tools/layoutlib/bridge/src/android/view/Display_Delegate.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2011 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.view; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - - -/** - * Delegate used to provide new implementation of a select few methods of {@link Display} - * - * Through the layoutlib_create tool, the original methods of Display have been replaced - * by calls to methods of the same name in this delegate class. - * - */ -public class Display_Delegate { - - @LayoutlibDelegate - static void updateDisplayInfoLocked(Display theDisplay) { - // do nothing - } - -} diff --git a/tools/layoutlib/bridge/src/android/view/HandlerActionQueue_Delegate.java b/tools/layoutlib/bridge/src/android/view/HandlerActionQueue_Delegate.java deleted file mode 100644 index e580ed0e14f7..000000000000 --- a/tools/layoutlib/bridge/src/android/view/HandlerActionQueue_Delegate.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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 android.view; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate used to provide new implementation of a select few methods of - * {@link HandlerActionQueue} - * - * Through the layoutlib_create tool, the original methods of ViewRootImpl.RunQueue have been - * replaced by calls to methods of the same name in this delegate class. - * - */ -public class HandlerActionQueue_Delegate { - - @LayoutlibDelegate - /*package*/ static void postDelayed(HandlerActionQueue thisQueue, Runnable action, long - delayMillis) { - // The actual HandlerActionQueue is never run and therefore never cleared. This method - // avoids runnables to be added to the RunQueue so they do not leak resources. - } -} diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java deleted file mode 100644 index 15fd2ceea5fa..000000000000 --- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java +++ /dev/null @@ -1,528 +0,0 @@ -/* - * Copyright (C) 2011 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.view; - -import android.content.res.Configuration; -import android.graphics.Bitmap; -import android.graphics.Point; -import android.graphics.Rect; -import android.os.Bundle; -import android.os.IBinder; -import android.os.IRemoteCallback; -import android.os.ParcelFileDescriptor; -import android.os.RemoteException; -import android.util.DisplayMetrics; - -import com.android.internal.app.IAssistScreenshotReceiver; -import com.android.internal.os.IResultReceiver; -import com.android.internal.policy.IKeyguardDismissCallback; -import com.android.internal.policy.IShortcutService; -import com.android.internal.view.IInputContext; -import com.android.internal.view.IInputMethodClient; - -/** - * Basic implementation of {@link IWindowManager} so that {@link Display} (and - * {@link Display_Delegate}) can return a valid instance. - */ -public class IWindowManagerImpl implements IWindowManager { - - private final Configuration mConfig; - private final DisplayMetrics mMetrics; - private final int mRotation; - private final boolean mHasNavigationBar; - - public IWindowManagerImpl(Configuration config, DisplayMetrics metrics, int rotation, - boolean hasNavigationBar) { - mConfig = config; - mMetrics = metrics; - mRotation = rotation; - mHasNavigationBar = hasNavigationBar; - } - - // custom API. - - public DisplayMetrics getMetrics() { - return mMetrics; - } - - // ---- implementation of IWindowManager that we care about ---- - - @Override - public int getDefaultDisplayRotation() throws RemoteException { - return mRotation; - } - - @Override - public boolean hasNavigationBar() { - return mHasNavigationBar; - } - - // ---- unused implementation of IWindowManager ---- - - @Override - public void addWindowToken(IBinder arg0, int arg1, int arg2) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void clearForcedDisplaySize(int displayId) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void clearForcedDisplayDensityForUser(int displayId, int userId) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void setOverscan(int displayId, int left, int top, int right, int bottom) - throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void closeSystemDialogs(String arg0) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void startFreezingScreen(int exitAnim, int enterAnim) { - // TODO Auto-generated method stub - } - - @Override - public void stopFreezingScreen() { - // TODO Auto-generated method stub - } - - @Override - public void disableKeyguard(IBinder arg0, String arg1) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void executeAppTransition() throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void exitKeyguardSecurely(IOnKeyguardExitResult arg0) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void freezeRotation(int arg0) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public float getAnimationScale(int arg0) throws RemoteException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public float[] getAnimationScales() throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getPendingAppTransition() throws RemoteException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public boolean inKeyguardRestrictedInputMode() throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean inputMethodClientHasFocus(IInputMethodClient arg0) throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean isKeyguardLocked() throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean isKeyguardSecure() throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean isViewServerRunning() throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public IWindowSession openSession(IWindowSessionCallback argn1, IInputMethodClient arg0, - IInputContext arg1) throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public void overridePendingAppTransition(String arg0, int arg1, int arg2, - IRemoteCallback startedCallback) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth, - int startHeight) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void overridePendingAppTransitionClipReveal(int startX, int startY, - int startWidth, int startHeight) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY, - IRemoteCallback startedCallback, boolean scaleUp) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX, - int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback, - boolean scaleUp) { - // TODO Auto-generated method stub - } - - @Override - public void overridePendingAppTransitionInPlace(String packageName, int anim) { - // TODO Auto-generated method stub - } - - @Override - public void overridePendingAppTransitionMultiThumbFuture( - IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback startedCallback, - boolean scaleUp) throws RemoteException { - - } - - @Override - public void overridePendingAppTransitionMultiThumb(AppTransitionAnimationSpec[] specs, - IRemoteCallback callback0, IRemoteCallback callback1, boolean scaleUp) { - // TODO Auto-generated method stub - } - - @Override - public void prepareAppTransition(int arg0, boolean arg1) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void reenableKeyguard(IBinder arg0) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void removeWindowToken(IBinder arg0, int arg1) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public boolean requestAssistScreenshot(IAssistScreenshotReceiver receiver) - throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public void setAnimationScale(int arg0, float arg1) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void setAnimationScales(float[] arg0) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public float getCurrentAnimatorScale() throws RemoteException { - return 0; - } - - @Override - public void setEventDispatching(boolean arg0) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void setFocusedApp(IBinder arg0, boolean arg1) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void getInitialDisplaySize(int displayId, Point size) { - // TODO Auto-generated method stub - } - - @Override - public void getBaseDisplaySize(int displayId, Point size) { - // TODO Auto-generated method stub - } - - @Override - public void setForcedDisplaySize(int displayId, int arg0, int arg1) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public int getInitialDisplayDensity(int displayId) { - return -1; - } - - @Override - public int getBaseDisplayDensity(int displayId) { - return -1; - } - - @Override - public void setForcedDisplayDensityForUser(int displayId, int density, int userId) - throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void setForcedDisplayScalingMode(int displayId, int mode) { - } - - @Override - public void setInTouchMode(boolean arg0) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public int[] setNewDisplayOverrideConfiguration(Configuration arg0, int displayId) - throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public void setScreenCaptureDisabled(int userId, boolean disabled) { - // TODO Auto-generated method stub - } - - @Override - public void updateRotation(boolean arg0, boolean arg1) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void setStrictModeVisualIndicatorPreference(String arg0) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void showStrictModeViolation(boolean arg0) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public boolean startViewServer(int arg0) throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public void statusBarVisibilityChanged(int arg0) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void setRecentsVisibility(boolean visible) { - // TODO Auto-generated method stub - } - - @Override - public void setPipVisibility(boolean visible) { - // TODO Auto-generated method stub - } - - @Override - public boolean stopViewServer() throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public void thawRotation() throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public Configuration updateOrientationFromAppTokens(Configuration arg0, IBinder arg1, int arg2) - throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public int watchRotation(IRotationWatcher arg0, int arg1) throws RemoteException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public void removeRotationWatcher(IRotationWatcher arg0) throws RemoteException { - } - - @Override - public IBinder asBinder() { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getPreferredOptionsPanelGravity() throws RemoteException { - return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; - } - - @Override - public void dismissKeyguard(IKeyguardDismissCallback callback) throws RemoteException { - } - - @Override - public void setSwitchingUser(boolean switching) throws RemoteException { - } - - @Override - public void lockNow(Bundle options) { - // TODO Auto-generated method stub - } - - @Override - public boolean isSafeModeEnabled() { - return false; - } - - @Override - public boolean isRotationFrozen() throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public void enableScreenIfNeeded() throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public boolean clearWindowContentFrameStats(IBinder token) throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public WindowContentFrameStats getWindowContentFrameStats(IBinder token) - throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getDockedStackSide() throws RemoteException { - return 0; - } - - @Override - public void setDockedStackResizing(boolean resizing) throws RemoteException { - } - - @Override - public void endProlongedAnimations() { - } - - @Override - public void registerDockedStackListener(IDockedStackListener listener) throws RemoteException { - } - - @Override - public void registerPinnedStackListener(int displayId, IPinnedStackListener listener) throws RemoteException { - } - - @Override - public void setResizeDimLayer(boolean visible, int targetStackId, float alpha) - throws RemoteException { - } - - @Override - public void setDockedStackDividerTouchRegion(Rect touchableRegion) throws RemoteException { - } - - @Override - public void requestAppKeyboardShortcuts( - IResultReceiver receiver, int deviceId) throws RemoteException { - } - - @Override - public void getStableInsets(int displayId, Rect outInsets) throws RemoteException { - } - - @Override - public void registerShortcutKey(long shortcutCode, IShortcutService service) - throws RemoteException {} - - @Override - public void createInputConsumer(String name, InputChannel inputChannel) - throws RemoteException {} - - @Override - public boolean destroyInputConsumer(String name) throws RemoteException { - return false; - } - - @Override - public Bitmap screenshotWallpaper() throws RemoteException { - return null; - } - - @Override - public void enableSurfaceTrace(ParcelFileDescriptor fd) throws RemoteException { - } - - @Override - public void disableSurfaceTrace() throws RemoteException { - } -} diff --git a/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java b/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java deleted file mode 100644 index cec6bb3844db..000000000000 --- a/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (C) 2011 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.view; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.layoutlib.bridge.Bridge; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import android.content.Context; -import android.content.res.TypedArray; -import android.content.res.XmlResourceParser; -import android.util.AttributeSet; -import android.util.TypedValue; -import android.util.Xml; - -import java.io.IOException; - -/** - * Delegate used to provide new implementation of a select few methods of {@link LayoutInflater} - * - * Through the layoutlib_create tool, the original methods of LayoutInflater have been replaced - * by calls to methods of the same name in this delegate class. - * - */ -public class LayoutInflater_Delegate { - private static final String TAG_MERGE = "merge"; - - private static final String ATTR_LAYOUT = "layout"; - - private static final int[] ATTRS_THEME = new int[] { - com.android.internal.R.attr.theme }; - - public static boolean sIsInInclude = false; - - /** - * Recursive method used to descend down the xml hierarchy and instantiate - * views, instantiate their children, and then call onFinishInflate(). - * - * This implementation just records the merge status before calling the default implementation. - */ - @LayoutlibDelegate - /* package */ static void rInflate(LayoutInflater thisInflater, XmlPullParser parser, - View parent, Context context, AttributeSet attrs, boolean finishInflate) - throws XmlPullParserException, IOException { - - if (finishInflate == false) { - // this is a merge rInflate! - if (thisInflater instanceof BridgeInflater) { - ((BridgeInflater) thisInflater).setIsInMerge(true); - } - } - - // ---- START DEFAULT IMPLEMENTATION. - - thisInflater.rInflate_Original(parser, parent, context, attrs, finishInflate); - - // ---- END DEFAULT IMPLEMENTATION. - - if (finishInflate == false) { - // this is a merge rInflate! - if (thisInflater instanceof BridgeInflater) { - ((BridgeInflater) thisInflater).setIsInMerge(false); - } - } - } - - @LayoutlibDelegate - public static void parseInclude(LayoutInflater thisInflater, XmlPullParser parser, - Context context, View parent, AttributeSet attrs) - throws XmlPullParserException, IOException { - int type; - - if (parent instanceof ViewGroup) { - // Apply a theme wrapper, if requested. This is sort of a weird - // edge case, since developers think the <include> overwrites - // values in the AttributeSet of the included View. So, if the - // included View has a theme attribute, we'll need to ignore it. - final TypedArray ta = context.obtainStyledAttributes(attrs, ATTRS_THEME); - final int themeResId = ta.getResourceId(0, 0); - final boolean hasThemeOverride = themeResId != 0; - if (hasThemeOverride) { - context = new ContextThemeWrapper(context, themeResId); - } - ta.recycle(); - - // If the layout is pointing to a theme attribute, we have to - // massage the value to get a resource identifier out of it. - int layout = attrs.getAttributeResourceValue(null, ATTR_LAYOUT, 0); - if (layout == 0) { - final String value = attrs.getAttributeValue(null, ATTR_LAYOUT); - if (value == null || value.length() <= 0) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, "You must specify a layout in the" - + " include tag: <include layout=\"@layout/layoutID\" />", null); - LayoutInflater.consumeChildElements(parser); - return; - } - - // Attempt to resolve the "?attr/name" string to an identifier. - layout = context.getResources().getIdentifier(value.substring(1), null, null); - } - - // The layout might be referencing a theme attribute. - // ---- START CHANGES - if (layout != 0) { - final TypedValue tempValue = new TypedValue(); - if (context.getTheme().resolveAttribute(layout, tempValue, true)) { - layout = tempValue.resourceId; - } - } - // ---- END CHANGES - - if (layout == 0) { - final String value = attrs.getAttributeValue(null, ATTR_LAYOUT); - if (value == null) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, "You must specify a layout in the" - + " include tag: <include layout=\"@layout/layoutID\" />", null); - } else { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, "You must specify a valid layout " - + "reference. The layout ID " + value + " is not valid.", null); - } - } else { - final XmlResourceParser childParser = - thisInflater.getContext().getResources().getLayout(layout); - - try { - final AttributeSet childAttrs = Xml.asAttributeSet(childParser); - - while ((type = childParser.next()) != XmlPullParser.START_TAG && - type != XmlPullParser.END_DOCUMENT) { - // Empty. - } - - if (type != XmlPullParser.START_TAG) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - childParser.getPositionDescription() + ": No start tag found!", - null); - LayoutInflater.consumeChildElements(parser); - return; - } - - final String childName = childParser.getName(); - - if (TAG_MERGE.equals(childName)) { - // Inflate all children. - thisInflater.rInflate(childParser, parent, context, childAttrs, false); - } else { - final View view = thisInflater.createViewFromTag(parent, childName, - context, childAttrs, hasThemeOverride); - final ViewGroup group = (ViewGroup) parent; - - final TypedArray a = context.obtainStyledAttributes( - attrs, com.android.internal.R.styleable.Include); - final int id = a.getResourceId( - com.android.internal.R.styleable.Include_id, View.NO_ID); - final int visibility = a.getInt( - com.android.internal.R.styleable.Include_visibility, -1); - a.recycle(); - - // We try to load the layout params set in the <include /> tag. If - // they don't exist, we will rely on the layout params set in the - // included XML file. - // During a layoutparams generation, a runtime exception is thrown - // if either layout_width or layout_height is missing. We catch - // this exception and set localParams accordingly: true means we - // successfully loaded layout params from the <include /> tag, - // false means we need to rely on the included layout params. - ViewGroup.LayoutParams params = null; - try { - // ---- START CHANGES - sIsInInclude = true; - // ---- END CHANGES - - params = group.generateLayoutParams(attrs); - } catch (RuntimeException ignored) { - // Ignore, just fail over to child attrs. - } finally { - // ---- START CHANGES - sIsInInclude = false; - // ---- END CHANGES - } - if (params == null) { - params = group.generateLayoutParams(childAttrs); - } - view.setLayoutParams(params); - - // Inflate all children. - thisInflater.rInflateChildren(childParser, view, childAttrs, true); - - if (id != View.NO_ID) { - view.setId(id); - } - - switch (visibility) { - case 0: - view.setVisibility(View.VISIBLE); - break; - case 1: - view.setVisibility(View.INVISIBLE); - break; - case 2: - view.setVisibility(View.GONE); - break; - } - - group.addView(view); - } - } finally { - childParser.close(); - } - } - } else { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "<include /> can only be used inside of a ViewGroup", - null); - } - - LayoutInflater.consumeChildElements(parser); - } -} diff --git a/tools/layoutlib/bridge/src/android/view/MenuInflater_Delegate.java b/tools/layoutlib/bridge/src/android/view/MenuInflater_Delegate.java deleted file mode 100644 index 08a97d647938..000000000000 --- a/tools/layoutlib/bridge/src/android/view/MenuInflater_Delegate.java +++ /dev/null @@ -1,72 +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.view; - -import android.content.Context; -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.ide.common.rendering.api.ViewInfo; -import com.android.internal.view.menu.BridgeMenuItemImpl; -import com.android.internal.view.menu.MenuView; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.util.AttributeSet; - -/** - * Delegate used to provide new implementation of a select few methods of {@link MenuInflater} - * <p/> - * Through the layoutlib_create tool, the original methods of MenuInflater have been - * replaced by calls to methods of the same name in this delegate class. - * <p/> - * The main purpose of the class is to get the view key from the menu xml parser and add it to - * the menu item. The view key is used by the IDE to match the individual view elements to the - * corresponding xml tag in the menu/layout file. - * <p/> - * For Menus, the views may be reused and the {@link MenuItem} is a better object to hold the - * view key than the {@link MenuView.ItemView}. At the time of computation of the rest of {@link - * ViewInfo}, we check the corresponding view key in the menu item for the view and add it - */ -public class MenuInflater_Delegate { - - @LayoutlibDelegate - /*package*/ static void registerMenu(MenuInflater thisInflater, MenuItem menuItem, - AttributeSet attrs) { - if (menuItem instanceof BridgeMenuItemImpl) { - Context context = thisInflater.getContext(); - context = BridgeContext.getBaseContext(context); - if (context instanceof BridgeContext) { - Object viewKey = BridgeInflater.getViewKeyFromParser( - attrs, ((BridgeContext) context), null, false); - ((BridgeMenuItemImpl) menuItem).setViewCookie(viewKey); - return; - } - } - // This means that Bridge did not take over the instantiation of some object properly. - // This is most likely a bug in the LayoutLib code. - Bridge.getLog().warning(LayoutLog.TAG_BROKEN, - "Action Bar Menu rendering may be incorrect.", null); - - } - - @LayoutlibDelegate - /*package*/ static void registerMenu(MenuInflater thisInflater, SubMenu subMenu, - AttributeSet parser) { - registerMenu(thisInflater, subMenu.getItem(), parser); - } - -} diff --git a/tools/layoutlib/bridge/src/android/view/PointerIcon_Delegate.java b/tools/layoutlib/bridge/src/android/view/PointerIcon_Delegate.java deleted file mode 100644 index 4a5ea9b5bb65..000000000000 --- a/tools/layoutlib/bridge/src/android/view/PointerIcon_Delegate.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 android.view; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.content.Context; -import android.content.res.Resources; - -public class PointerIcon_Delegate { - - @LayoutlibDelegate - /*package*/ static void loadResource(PointerIcon icon, Context context, Resources resources, - int resourceId) { - // HACK: This bypasses the problem of having an enum resolved as a resourceId. - // PointerIcon would not be displayed by layoutlib anyway, so we always return the null - // icon. - } -} diff --git a/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java b/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java deleted file mode 100644 index 08665778373e..000000000000 --- a/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright (C) 2015, 2017 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.view; - -import android.annotation.NonNull; -import android.graphics.Canvas; -import android.graphics.LinearGradient; -import android.graphics.Outline; -import android.graphics.Paint; -import android.graphics.Paint.Style; -import android.graphics.Path; -import android.graphics.Path.FillType; -import android.graphics.RadialGradient; -import android.graphics.Rect; -import android.graphics.RectF; -import android.graphics.Shader.TileMode; - -import com.android.layoutlib.bridge.impl.ResourceHelper; -import com.android.layoutlib.bridge.shadowutil.SpotShadow; -import com.android.layoutlib.bridge.shadowutil.ShadowBuffer; - -public class RectShadowPainter { - - private static final float SIMPLE_SHADOW_ELEVATION_THRESHOLD = 16f; - private static final int SIMPLE_SHADOW_START_COLOR = ResourceHelper.getColor("#37000000"); - private static final int SIMPLE_SHADOW_END_COLOR = ResourceHelper.getColor("#03000000"); - private static final float PERPENDICULAR_ANGLE = 90f; - - private static final float SHADOW_STRENGTH = 0.1f; - private static final int LIGHT_POINTS = 8; - - private static final int QUADRANT_DIVIDED_COUNT = 8; - - private static final int RAY_TRACING_RAYS = 180; - private static final int RAY_TRACING_LAYERS = 10; - - public static void paintShadow(@NonNull Outline viewOutline, float elevation, - @NonNull Canvas canvas) { - Rect outline = new Rect(); - if (!viewOutline.getRect(outline)) { - assert false : "Outline is not a rect shadow"; - return; - } - - if (elevation <= 0) { - // If elevation is 0, we don't need to paint the shadow - return; - } - - Rect originCanvasRect = canvas.getClipBounds(); - int saved = modifyCanvas(canvas); - if (saved == -1) { - return; - } - try { - float radius = viewOutline.getRadius(); - if (radius <= 0) { - // We can not paint a shadow with radius 0 - return; - } - - if (elevation <= SIMPLE_SHADOW_ELEVATION_THRESHOLD) { - // When elevation is not high, the shadow is very similar to a small outline of - // View. For the performance reason, we draw the shadow in simple way. - simpleRectangleShadow(canvas, outline, radius, elevation); - } else { - // view's absolute position in this canvas. - int viewLeft = -originCanvasRect.left + outline.left; - int viewTop = -originCanvasRect.top + outline.top; - int viewRight = viewLeft + outline.width(); - int viewBottom = viewTop + outline.height(); - - float[][] rectangleCoordinators = - generateRectangleCoordinates(viewLeft, viewTop, viewRight, viewBottom, - radius, elevation); - - // TODO: get these values from resources. - float lightPosX = canvas.getWidth() / 2; - float lightPosY = 0; - float lightHeight = 1800; - float lightSize = 200; - - paintGeometricShadow(rectangleCoordinators, lightPosX, lightPosY, lightHeight, - lightSize, canvas); - } - } finally { - canvas.restoreToCount(saved); - } - } - - private static int modifyCanvas(@NonNull Canvas canvas) { - Rect rect = canvas.getClipBounds(); - canvas.translate(rect.left, rect.top); - return canvas.save(); - } - - private static void simpleRectangleShadow(@NonNull Canvas canvas, @NonNull Rect outline, - float radius, float elevation) { - float shadowSize = elevation / 2; - - Paint cornerPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); - cornerPaint.setStyle(Style.FILL); - Paint edgePaint = new Paint(cornerPaint); - edgePaint.setAntiAlias(false); - float outerArcRadius = radius + shadowSize; - int[] colors = {SIMPLE_SHADOW_START_COLOR, SIMPLE_SHADOW_START_COLOR, - SIMPLE_SHADOW_END_COLOR}; - cornerPaint.setShader(new RadialGradient(0, 0, outerArcRadius, colors, - new float[]{0f, radius / outerArcRadius, 1f}, TileMode.CLAMP)); - edgePaint.setShader(new LinearGradient(0, 0, -shadowSize, 0, SIMPLE_SHADOW_START_COLOR, - SIMPLE_SHADOW_END_COLOR, - TileMode.CLAMP)); - Path path = new Path(); - path.setFillType(FillType.EVEN_ODD); - // A rectangle bounding the complete shadow. - RectF shadowRect = new RectF(outline); - shadowRect.inset(-shadowSize, -shadowSize); - // A rectangle with edges corresponding to the straight edges of the outline. - RectF inset = new RectF(outline); - inset.inset(radius, radius); - // A rectangle used to represent the edge shadow. - RectF edgeShadowRect = new RectF(); - - - // left and right sides. - edgeShadowRect.set(-shadowSize, 0f, 0f, inset.height()); - // Left shadow - drawSideShadow(canvas, edgePaint, edgeShadowRect, outline.left, inset.top, 0); - // Right shadow - drawSideShadow(canvas, edgePaint, edgeShadowRect, outline.right, inset.bottom, 2); - // Top shadow - edgeShadowRect.set(-shadowSize, 0, 0, inset.width()); - drawSideShadow(canvas, edgePaint, edgeShadowRect, inset.right, outline.top, 1); - // bottom shadow. This needs an inset so that blank doesn't appear when the content is - // moved up. - edgeShadowRect.set(-shadowSize, 0, shadowSize / 2f, inset.width()); - edgePaint.setShader( - new LinearGradient(edgeShadowRect.right, 0, edgeShadowRect.left, 0, colors, - new float[]{0f, 1 / 3f, 1f}, TileMode.CLAMP)); - drawSideShadow(canvas, edgePaint, edgeShadowRect, inset.left, outline.bottom, 3); - - // Draw corners. - drawCorner(canvas, cornerPaint, path, inset.right, inset.bottom, outerArcRadius, 0); - drawCorner(canvas, cornerPaint, path, inset.left, inset.bottom, outerArcRadius, 1); - drawCorner(canvas, cornerPaint, path, inset.left, inset.top, outerArcRadius, 2); - drawCorner(canvas, cornerPaint, path, inset.right, inset.top, outerArcRadius, 3); - } - - private static void drawSideShadow(@NonNull Canvas canvas, @NonNull Paint edgePaint, - @NonNull RectF shadowRect, float dx, float dy, int rotations) { - if ((int) shadowRect.left >= (int) shadowRect.right || - (int) shadowRect.top >= (int) shadowRect.bottom) { - // Rect is empty, no need to draw shadow - return; - } - int saved = canvas.save(); - canvas.translate(dx, dy); - canvas.rotate(rotations * PERPENDICULAR_ANGLE); - canvas.drawRect(shadowRect, edgePaint); - canvas.restoreToCount(saved); - } - - /** - * @param canvas Canvas to draw the rectangle on. - * @param paint Paint to use when drawing the corner. - * @param path A path to reuse. Prevents allocating memory for each path. - * @param x Center of circle, which this corner is a part of. - * @param y Center of circle, which this corner is a part of. - * @param radius radius of the arc - * @param rotations number of quarter rotations before starting to paint the arc. - */ - private static void drawCorner(@NonNull Canvas canvas, @NonNull Paint paint, @NonNull Path path, - float x, float y, float radius, int rotations) { - int saved = canvas.save(); - canvas.translate(x, y); - path.reset(); - path.arcTo(-radius, -radius, radius, radius, rotations * PERPENDICULAR_ANGLE, - PERPENDICULAR_ANGLE, false); - path.lineTo(0, 0); - path.close(); - canvas.drawPath(path, paint); - canvas.restoreToCount(saved); - } - - @NonNull - private static float[][] generateRectangleCoordinates(float left, float top, float right, - float bottom, float radius, float elevation) { - left = left + radius; - top = top + radius; - right = right - radius; - bottom = bottom - radius; - - final double RADIANS_STEP = 2 * Math.PI / 4 / QUADRANT_DIVIDED_COUNT; - - float[][] ret = new float[QUADRANT_DIVIDED_COUNT * 4][3]; - - int points = 0; - // left-bottom points - for (int i = 0; i < QUADRANT_DIVIDED_COUNT; i++) { - ret[points][0] = (float) (left - radius + radius * Math.cos(RADIANS_STEP * i)); - ret[points][1] = (float) (bottom + radius - radius * Math.cos(RADIANS_STEP * i)); - ret[points][2] = elevation; - points++; - } - // left-top points - for (int i = 0; i < QUADRANT_DIVIDED_COUNT; i++) { - ret[points][0] = (float) (left + radius - radius * Math.cos(RADIANS_STEP * i)); - ret[points][1] = (float) (top + radius - radius * Math.cos(RADIANS_STEP * i)); - ret[points][2] = elevation; - points++; - } - // right-top points - for (int i = 0; i < QUADRANT_DIVIDED_COUNT; i++) { - ret[points][0] = (float) (right + radius - radius * Math.cos(RADIANS_STEP * i)); - ret[points][1] = (float) (top + radius + radius * Math.cos(RADIANS_STEP * i)); - ret[points][2] = elevation; - points++; - } - // right-bottom point - for (int i = 0; i < QUADRANT_DIVIDED_COUNT; i++) { - ret[points][0] = (float) (right - radius + radius * Math.cos(RADIANS_STEP * i)); - ret[points][1] = (float) (bottom - radius + radius * Math.cos(RADIANS_STEP * i)); - ret[points][2] = elevation; - points++; - } - - return ret; - } - - private static void paintGeometricShadow(@NonNull float[][] coordinates, float lightPosX, - float lightPosY, float lightHeight, float lightSize, Canvas canvas) { - if (canvas == null || canvas.getWidth() == 0 || canvas.getHeight() == 0) { - return; - } - - // The polygon of shadow (same as the original item) - float[] shadowPoly = new float[coordinates.length * 3]; - for (int i = 0; i < coordinates.length; i++) { - shadowPoly[i * 3 + 0] = coordinates[i][0]; - shadowPoly[i * 3 + 1] = coordinates[i][1]; - shadowPoly[i * 3 + 2] = coordinates[i][2]; - } - - // TODO: calculate the ambient shadow and mix with Spot shadow. - - // Calculate the shadow of SpotLight - float[] light = SpotShadow.calculateLight(lightSize, LIGHT_POINTS, lightPosX, - lightPosY, lightHeight); - - int stripSize = 3 * SpotShadow.getStripSize(RAY_TRACING_RAYS, RAY_TRACING_LAYERS); - if (stripSize < 9) { - return; - } - float[] strip = new float[stripSize]; - SpotShadow.calcShadow(light, LIGHT_POINTS, shadowPoly, coordinates.length, RAY_TRACING_RAYS, - RAY_TRACING_LAYERS, 1f, strip); - - ShadowBuffer buff = new ShadowBuffer(canvas.getWidth(), canvas.getHeight()); - buff.generateTriangles(strip, SHADOW_STRENGTH); - buff.draw(canvas); - } -} diff --git a/tools/layoutlib/bridge/src/android/view/RenderNode_Delegate.java b/tools/layoutlib/bridge/src/android/view/RenderNode_Delegate.java deleted file mode 100644 index 152878bb0fd5..000000000000 --- a/tools/layoutlib/bridge/src/android/view/RenderNode_Delegate.java +++ /dev/null @@ -1,335 +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.view; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.graphics.Matrix; - -import libcore.util.NativeAllocationRegistry_Delegate; - -/** - * Delegate implementing the native methods of {@link RenderNode} - * <p/> - * Through the layoutlib_create tool, some native methods of RenderNode have been replaced by calls - * to methods of the same name in this delegate class. - * - * @see DelegateManager - */ -public class RenderNode_Delegate { - - - // ---- delegate manager ---- - private static final DelegateManager<RenderNode_Delegate> sManager = - new DelegateManager<RenderNode_Delegate>(RenderNode_Delegate.class); - private static long sFinalizer = -1; - - private float mLift; - private float mTranslationX; - private float mTranslationY; - private float mTranslationZ; - private float mRotation; - private float mScaleX = 1; - private float mScaleY = 1; - private float mPivotX; - private float mPivotY; - private boolean mPivotExplicitlySet; - private int mLeft; - private int mRight; - private int mTop; - private int mBottom; - @SuppressWarnings("UnusedDeclaration") - private String mName; - - @LayoutlibDelegate - /*package*/ static long nCreate(String name) { - RenderNode_Delegate renderNodeDelegate = new RenderNode_Delegate(); - renderNodeDelegate.mName = name; - return sManager.addNewDelegate(renderNodeDelegate); - } - - @LayoutlibDelegate - /*package*/ static long nGetNativeFinalizer() { - synchronized (RenderNode_Delegate.class) { - if (sFinalizer == -1) { - sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(sManager::removeJavaReferenceFor); - } - } - return sFinalizer; - } - - @LayoutlibDelegate - /*package*/ static boolean nSetElevation(long renderNode, float lift) { - RenderNode_Delegate delegate = sManager.getDelegate(renderNode); - if (delegate != null && delegate.mLift != lift) { - delegate.mLift = lift; - return true; - } - return false; - } - - @LayoutlibDelegate - /*package*/ static float nGetElevation(long renderNode) { - RenderNode_Delegate delegate = sManager.getDelegate(renderNode); - if (delegate != null) { - return delegate.mLift; - } - return 0f; - } - - @LayoutlibDelegate - /*package*/ static boolean nSetTranslationX(long renderNode, float translationX) { - RenderNode_Delegate delegate = sManager.getDelegate(renderNode); - if (delegate != null && delegate.mTranslationX != translationX) { - delegate.mTranslationX = translationX; - return true; - } - return false; - } - - @LayoutlibDelegate - /*package*/ static float nGetTranslationX(long renderNode) { - RenderNode_Delegate delegate = sManager.getDelegate(renderNode); - if (delegate != null) { - return delegate.mTranslationX; - } - return 0f; - } - - @LayoutlibDelegate - /*package*/ static boolean nSetTranslationY(long renderNode, float translationY) { - RenderNode_Delegate delegate = sManager.getDelegate(renderNode); - if (delegate != null && delegate.mTranslationY != translationY) { - delegate.mTranslationY = translationY; - return true; - } - return false; - } - - @LayoutlibDelegate - /*package*/ static float nGetTranslationY(long renderNode) { - RenderNode_Delegate delegate = sManager.getDelegate(renderNode); - if (delegate != null) { - return delegate.mTranslationY; - } - return 0f; - } - - @LayoutlibDelegate - /*package*/ static boolean nSetTranslationZ(long renderNode, float translationZ) { - RenderNode_Delegate delegate = sManager.getDelegate(renderNode); - if (delegate != null && delegate.mTranslationZ != translationZ) { - delegate.mTranslationZ = translationZ; - return true; - } - return false; - } - - @LayoutlibDelegate - /*package*/ static float nGetTranslationZ(long renderNode) { - RenderNode_Delegate delegate = sManager.getDelegate(renderNode); - if (delegate != null) { - return delegate.mTranslationZ; - } - return 0f; - } - - @LayoutlibDelegate - /*package*/ static boolean nSetRotation(long renderNode, float rotation) { - RenderNode_Delegate delegate = sManager.getDelegate(renderNode); - if (delegate != null && delegate.mRotation != rotation) { - delegate.mRotation = rotation; - return true; - } - return false; - } - - @LayoutlibDelegate - /*package*/ static float nGetRotation(long renderNode) { - RenderNode_Delegate delegate = sManager.getDelegate(renderNode); - if (delegate != null) { - return delegate.mRotation; - } - return 0f; - } - - @LayoutlibDelegate - /*package*/ static void getMatrix(RenderNode renderNode, Matrix outMatrix) { - outMatrix.reset(); - if (renderNode != null) { - float rotation = renderNode.getRotation(); - float translationX = renderNode.getTranslationX(); - float translationY = renderNode.getTranslationY(); - float pivotX = renderNode.getPivotX(); - float pivotY = renderNode.getPivotY(); - float scaleX = renderNode.getScaleX(); - float scaleY = renderNode.getScaleY(); - - outMatrix.setTranslate(translationX, translationY); - outMatrix.preRotate(rotation, pivotX, pivotY); - outMatrix.preScale(scaleX, scaleY, pivotX, pivotY); - } - } - - @LayoutlibDelegate - /*package*/ static boolean nSetLeft(long renderNode, int left) { - RenderNode_Delegate delegate = sManager.getDelegate(renderNode); - if (delegate != null && delegate.mLeft != left) { - delegate.mLeft = left; - return true; - } - return false; - } - - @LayoutlibDelegate - /*package*/ static boolean nSetTop(long renderNode, int top) { - RenderNode_Delegate delegate = sManager.getDelegate(renderNode); - if (delegate != null && delegate.mTop != top) { - delegate.mTop = top; - return true; - } - return false; - } - - @LayoutlibDelegate - /*package*/ static boolean nSetRight(long renderNode, int right) { - RenderNode_Delegate delegate = sManager.getDelegate(renderNode); - if (delegate != null && delegate.mRight != right) { - delegate.mRight = right; - return true; - } - return false; - } - - @LayoutlibDelegate - /*package*/ static boolean nSetBottom(long renderNode, int bottom) { - RenderNode_Delegate delegate = sManager.getDelegate(renderNode); - if (delegate != null && delegate.mBottom != bottom) { - delegate.mBottom = bottom; - return true; - } - return false; - } - - @LayoutlibDelegate - /*package*/ static boolean nSetLeftTopRightBottom(long renderNode, int left, int top, int right, - int bottom) { - RenderNode_Delegate delegate = sManager.getDelegate(renderNode); - if (delegate != null && (delegate.mLeft != left || delegate.mTop != top || delegate - .mRight != right || delegate.mBottom != bottom)) { - delegate.mLeft = left; - delegate.mTop = top; - delegate.mRight = right; - delegate.mBottom = bottom; - return true; - } - return false; - } - - @LayoutlibDelegate - /*package*/ static boolean nIsPivotExplicitlySet(long renderNode) { - RenderNode_Delegate delegate = sManager.getDelegate(renderNode); - return delegate != null && delegate.mPivotExplicitlySet; - } - - @LayoutlibDelegate - /*package*/ static boolean nSetPivotX(long renderNode, float pivotX) { - RenderNode_Delegate delegate = sManager.getDelegate(renderNode); - if (delegate != null) { - delegate.mPivotX = pivotX; - delegate.mPivotExplicitlySet = true; - return true; - } - return false; - } - - @LayoutlibDelegate - /*package*/ static float nGetPivotX(long renderNode) { - RenderNode_Delegate delegate = sManager.getDelegate(renderNode); - if (delegate != null) { - if (delegate.mPivotExplicitlySet) { - return delegate.mPivotX; - } else { - return (delegate.mRight - delegate.mLeft) / 2.0f; - } - } - return 0f; - } - - @LayoutlibDelegate - /*package*/ static boolean nSetPivotY(long renderNode, float pivotY) { - RenderNode_Delegate delegate = sManager.getDelegate(renderNode); - if (delegate != null) { - delegate.mPivotY = pivotY; - delegate.mPivotExplicitlySet = true; - return true; - } - return false; - } - - @LayoutlibDelegate - /*package*/ static float nGetPivotY(long renderNode) { - RenderNode_Delegate delegate = sManager.getDelegate(renderNode); - if (delegate != null) { - if (delegate.mPivotExplicitlySet) { - return delegate.mPivotY; - } else { - return (delegate.mBottom - delegate.mTop) / 2.0f; - } - } - return 0f; - } - - @LayoutlibDelegate - /*package*/ static boolean nSetScaleX(long renderNode, float scaleX) { - RenderNode_Delegate delegate = sManager.getDelegate(renderNode); - if (delegate != null && delegate.mScaleX != scaleX) { - delegate.mScaleX = scaleX; - return true; - } - return false; - } - - @LayoutlibDelegate - /*package*/ static float nGetScaleX(long renderNode) { - RenderNode_Delegate delegate = sManager.getDelegate(renderNode); - if (delegate != null) { - return delegate.mScaleX; - } - return 0f; - } - - @LayoutlibDelegate - /*package*/ static boolean nSetScaleY(long renderNode, float scaleY) { - RenderNode_Delegate delegate = sManager.getDelegate(renderNode); - if (delegate != null && delegate.mScaleY != scaleY) { - delegate.mScaleY = scaleY; - return true; - } - return false; - } - - @LayoutlibDelegate - /*package*/ static float nGetScaleY(long renderNode) { - RenderNode_Delegate delegate = sManager.getDelegate(renderNode); - if (delegate != null) { - return delegate.mScaleY; - } - return 0f; - } -} diff --git a/tools/layoutlib/bridge/src/android/view/ShadowPainter.java b/tools/layoutlib/bridge/src/android/view/ShadowPainter.java deleted file mode 100644 index f09fffd10291..000000000000 --- a/tools/layoutlib/bridge/src/android/view/ShadowPainter.java +++ /dev/null @@ -1,422 +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.view; - -import android.annotation.NonNull; - -import java.awt.Graphics2D; -import java.awt.Image; -import java.awt.image.BufferedImage; -import java.awt.image.DataBufferInt; -import java.io.IOException; -import java.io.InputStream; - -import javax.imageio.ImageIO; - -public class ShadowPainter { - - /** - * Adds a drop shadow to a semi-transparent image (of an arbitrary shape) and returns it as a - * new image. This method attempts to mimic the same visual characteristics as the rectangular - * shadow painting methods in this class, {@link #createRectangularDropShadow(java.awt.image.BufferedImage)} - * and {@link #createSmallRectangularDropShadow(java.awt.image.BufferedImage)}. - * <p/> - * If shadowSize is less or equals to 1, no shadow will be painted and the source image will be - * returned instead. - * - * @param source the source image - * @param shadowSize the size of the shadow, normally {@link #SHADOW_SIZE or {@link - * #SMALL_SHADOW_SIZE}} - * - * @return an image with the shadow painted in or the source image if shadowSize <= 1 - */ - @NonNull - public static BufferedImage createDropShadow(BufferedImage source, int shadowSize) { - shadowSize /= 2; // make shadow size have the same meaning as in the other shadow paint methods in this class - - return createDropShadow(source, shadowSize, 0.7f, 0); - } - - /** - * Creates a drop shadow of a given image and returns a new image which shows the input image on - * top of its drop shadow. - * <p/> - * <b>NOTE: If the shape is rectangular and opaque, consider using {@link - * #drawRectangleShadow(Graphics2D, int, int, int, int)} instead.</b> - * - * @param source the source image to be shadowed - * @param shadowSize the size of the shadow in pixels - * @param shadowOpacity the opacity of the shadow, with 0=transparent and 1=opaque - * @param shadowRgb the RGB int to use for the shadow color - * - * @return a new image with the source image on top of its shadow when shadowSize > 0 or the - * source image otherwise - */ - @SuppressWarnings({"SuspiciousNameCombination", "UnnecessaryLocalVariable"}) // Imported code - public static BufferedImage createDropShadow(BufferedImage source, int shadowSize, - float shadowOpacity, int shadowRgb) { - if (shadowSize <= 0) { - return source; - } - - // This code is based on - // http://www.jroller.com/gfx/entry/non_rectangular_shadow - - BufferedImage image; - int width = source.getWidth(); - int height = source.getHeight(); - image = new BufferedImage(width + SHADOW_SIZE, height + SHADOW_SIZE, - BufferedImage.TYPE_INT_ARGB); - - Graphics2D g2 = image.createGraphics(); - g2.drawImage(image, shadowSize, shadowSize, null); - - int dstWidth = image.getWidth(); - int dstHeight = image.getHeight(); - - int left = (shadowSize - 1) >> 1; - int right = shadowSize - left; - int xStart = left; - int xStop = dstWidth - right; - int yStart = left; - int yStop = dstHeight - right; - - shadowRgb &= 0x00FFFFFF; - - int[] aHistory = new int[shadowSize]; - int historyIdx; - - int aSum; - - int[] dataBuffer = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); - int lastPixelOffset = right * dstWidth; - float sumDivider = shadowOpacity / shadowSize; - - // horizontal pass - for (int y = 0, bufferOffset = 0; y < dstHeight; y++, bufferOffset = y * dstWidth) { - aSum = 0; - historyIdx = 0; - for (int x = 0; x < shadowSize; x++, bufferOffset++) { - int a = dataBuffer[bufferOffset] >>> 24; - aHistory[x] = a; - aSum += a; - } - - bufferOffset -= right; - - for (int x = xStart; x < xStop; x++, bufferOffset++) { - int a = (int) (aSum * sumDivider); - dataBuffer[bufferOffset] = a << 24 | shadowRgb; - - // subtract the oldest pixel from the sum - aSum -= aHistory[historyIdx]; - - // get the latest pixel - a = dataBuffer[bufferOffset + right] >>> 24; - aHistory[historyIdx] = a; - aSum += a; - - if (++historyIdx >= shadowSize) { - historyIdx -= shadowSize; - } - } - } - // vertical pass - for (int x = 0, bufferOffset = 0; x < dstWidth; x++, bufferOffset = x) { - aSum = 0; - historyIdx = 0; - for (int y = 0; y < shadowSize; y++, bufferOffset += dstWidth) { - int a = dataBuffer[bufferOffset] >>> 24; - aHistory[y] = a; - aSum += a; - } - - bufferOffset -= lastPixelOffset; - - for (int y = yStart; y < yStop; y++, bufferOffset += dstWidth) { - int a = (int) (aSum * sumDivider); - dataBuffer[bufferOffset] = a << 24 | shadowRgb; - - // subtract the oldest pixel from the sum - aSum -= aHistory[historyIdx]; - - // get the latest pixel - a = dataBuffer[bufferOffset + lastPixelOffset] >>> 24; - aHistory[historyIdx] = a; - aSum += a; - - if (++historyIdx >= shadowSize) { - historyIdx -= shadowSize; - } - } - } - - g2.drawImage(source, null, 0, 0); - g2.dispose(); - - return image; - } - - /** - * Draws a rectangular drop shadow (of size {@link #SHADOW_SIZE} by {@link #SHADOW_SIZE} around - * the given source and returns a new image with both combined - * - * @param source the source image - * - * @return the source image with a drop shadow on the bottom and right - */ - @SuppressWarnings("UnusedDeclaration") - public static BufferedImage createRectangularDropShadow(BufferedImage source) { - int type = source.getType(); - if (type == BufferedImage.TYPE_CUSTOM) { - type = BufferedImage.TYPE_INT_ARGB; - } - - int width = source.getWidth(); - int height = source.getHeight(); - BufferedImage image; - image = new BufferedImage(width + SHADOW_SIZE, height + SHADOW_SIZE, type); - Graphics2D g = image.createGraphics(); - g.drawImage(source, 0, 0, null); - drawRectangleShadow(image, 0, 0, width, height); - g.dispose(); - - return image; - } - - /** - * Draws a small rectangular drop shadow (of size {@link #SMALL_SHADOW_SIZE} by {@link - * #SMALL_SHADOW_SIZE} around the given source and returns a new image with both combined - * - * @param source the source image - * - * @return the source image with a drop shadow on the bottom and right - */ - @SuppressWarnings("UnusedDeclaration") - public static BufferedImage createSmallRectangularDropShadow(BufferedImage source) { - int type = source.getType(); - if (type == BufferedImage.TYPE_CUSTOM) { - type = BufferedImage.TYPE_INT_ARGB; - } - - int width = source.getWidth(); - int height = source.getHeight(); - - BufferedImage image; - image = new BufferedImage(width + SMALL_SHADOW_SIZE, height + SMALL_SHADOW_SIZE, type); - - Graphics2D g = image.createGraphics(); - g.drawImage(source, 0, 0, null); - drawSmallRectangleShadow(image, 0, 0, width, height); - g.dispose(); - - return image; - } - - /** - * Draws a drop shadow for the given rectangle into the given context. It will not draw anything - * if the rectangle is smaller than a minimum determined by the assets used to draw the shadow - * graphics. The size of the shadow is {@link #SHADOW_SIZE}. - * - * @param image the image to draw the shadow into - * @param x the left coordinate of the left hand side of the rectangle - * @param y the top coordinate of the top of the rectangle - * @param width the width of the rectangle - * @param height the height of the rectangle - */ - public static void drawRectangleShadow(BufferedImage image, - int x, int y, int width, int height) { - Graphics2D gc = image.createGraphics(); - try { - drawRectangleShadow(gc, x, y, width, height); - } finally { - gc.dispose(); - } - } - - /** - * Draws a small drop shadow for the given rectangle into the given context. It will not draw - * anything if the rectangle is smaller than a minimum determined by the assets used to draw the - * shadow graphics. The size of the shadow is {@link #SMALL_SHADOW_SIZE}. - * - * @param image the image to draw the shadow into - * @param x the left coordinate of the left hand side of the rectangle - * @param y the top coordinate of the top of the rectangle - * @param width the width of the rectangle - * @param height the height of the rectangle - */ - public static void drawSmallRectangleShadow(BufferedImage image, - int x, int y, int width, int height) { - Graphics2D gc = image.createGraphics(); - try { - drawSmallRectangleShadow(gc, x, y, width, height); - } finally { - gc.dispose(); - } - } - - /** - * The width and height of the drop shadow painted by - * {@link #drawRectangleShadow(Graphics2D, int, int, int, int)} - */ - public static final int SHADOW_SIZE = 20; // DO NOT EDIT. This corresponds to bitmap graphics - - /** - * The width and height of the drop shadow painted by - * {@link #drawSmallRectangleShadow(Graphics2D, int, int, int, int)} - */ - public static final int SMALL_SHADOW_SIZE = 10; // DO NOT EDIT. Corresponds to bitmap graphics - - /** - * Draws a drop shadow for the given rectangle into the given context. It will not draw anything - * if the rectangle is smaller than a minimum determined by the assets used to draw the shadow - * graphics. - * - * @param gc the graphics context to draw into - * @param x the left coordinate of the left hand side of the rectangle - * @param y the top coordinate of the top of the rectangle - * @param width the width of the rectangle - * @param height the height of the rectangle - */ - public static void drawRectangleShadow(Graphics2D gc, int x, int y, int width, int height) { - assert ShadowBottomLeft != null; - assert ShadowBottomRight.getWidth(null) == SHADOW_SIZE; - assert ShadowBottomRight.getHeight(null) == SHADOW_SIZE; - - int blWidth = ShadowBottomLeft.getWidth(null); - int trHeight = ShadowTopRight.getHeight(null); - if (width < blWidth) { - return; - } - if (height < trHeight) { - return; - } - - gc.drawImage(ShadowBottomLeft, x - ShadowBottomLeft.getWidth(null), y + height, null); - gc.drawImage(ShadowBottomRight, x + width, y + height, null); - gc.drawImage(ShadowTopRight, x + width, y, null); - gc.drawImage(ShadowTopLeft, x - ShadowTopLeft.getWidth(null), y, null); - gc.drawImage(ShadowBottom, - x, y + height, x + width, y + height + ShadowBottom.getHeight(null), - 0, 0, ShadowBottom.getWidth(null), ShadowBottom.getHeight(null), null); - gc.drawImage(ShadowRight, - x + width, y + ShadowTopRight.getHeight(null), x + width + ShadowRight.getWidth(null), y + height, - 0, 0, ShadowRight.getWidth(null), ShadowRight.getHeight(null), null); - gc.drawImage(ShadowLeft, - x - ShadowLeft.getWidth(null), y + ShadowTopLeft.getHeight(null), x, y + height, - 0, 0, ShadowLeft.getWidth(null), ShadowLeft.getHeight(null), null); - } - - /** - * Draws a small drop shadow for the given rectangle into the given context. It will not draw - * anything if the rectangle is smaller than a minimum determined by the assets used to draw the - * shadow graphics. - * <p/> - * - * @param gc the graphics context to draw into - * @param x the left coordinate of the left hand side of the rectangle - * @param y the top coordinate of the top of the rectangle - * @param width the width of the rectangle - * @param height the height of the rectangle - */ - public static void drawSmallRectangleShadow(Graphics2D gc, int x, int y, int width, - int height) { - assert Shadow2BottomLeft != null; - assert Shadow2TopRight != null; - assert Shadow2BottomRight.getWidth(null) == SMALL_SHADOW_SIZE; - assert Shadow2BottomRight.getHeight(null) == SMALL_SHADOW_SIZE; - - int blWidth = Shadow2BottomLeft.getWidth(null); - int trHeight = Shadow2TopRight.getHeight(null); - if (width < blWidth) { - return; - } - if (height < trHeight) { - return; - } - - gc.drawImage(Shadow2BottomLeft, x - Shadow2BottomLeft.getWidth(null), y + height, null); - gc.drawImage(Shadow2BottomRight, x + width, y + height, null); - gc.drawImage(Shadow2TopRight, x + width, y, null); - gc.drawImage(Shadow2TopLeft, x - Shadow2TopLeft.getWidth(null), y, null); - gc.drawImage(Shadow2Bottom, - x, y + height, x + width, y + height + Shadow2Bottom.getHeight(null), - 0, 0, Shadow2Bottom.getWidth(null), Shadow2Bottom.getHeight(null), null); - gc.drawImage(Shadow2Right, - x + width, y + Shadow2TopRight.getHeight(null), x + width + Shadow2Right.getWidth(null), y + height, - 0, 0, Shadow2Right.getWidth(null), Shadow2Right.getHeight(null), null); - gc.drawImage(Shadow2Left, - x - Shadow2Left.getWidth(null), y + Shadow2TopLeft.getHeight(null), x, y + height, - 0, 0, Shadow2Left.getWidth(null), Shadow2Left.getHeight(null), null); - } - - private static Image loadIcon(String name) { - InputStream inputStream = ShadowPainter.class.getResourceAsStream(name); - if (inputStream == null) { - throw new RuntimeException("Unable to load image for shadow: " + name); - } - try { - return ImageIO.read(inputStream); - } catch (IOException e) { - throw new RuntimeException("Unable to load image for shadow:" + name, e); - } finally { - try { - inputStream.close(); - } catch (IOException e) { - // ignore. - } - } - } - - // Shadow graphics. This was generated by creating a drop shadow in - // Gimp, using the parameters x offset=10, y offset=10, blur radius=10, - // (for the small drop shadows x offset=10, y offset=10, blur radius=10) - // color=black, and opacity=51. These values attempt to make a shadow - // that is legible both for dark and light themes, on top of the - // canvas background (rgb(150,150,150). Darker shadows would tend to - // blend into the foreground for a dark holo screen, and lighter shadows - // would be hard to spot on the canvas background. If you make adjustments, - // make sure to check the shadow with both dark and light themes. - // - // After making the graphics, I cut out the top right, bottom left - // and bottom right corners as 20x20 images, and these are reproduced by - // painting them in the corresponding places in the target graphics context. - // I then grabbed a single horizontal gradient line from the middle of the - // right edge,and a single vertical gradient line from the bottom. These - // are then painted scaled/stretched in the target to fill the gaps between - // the three corner images. - // - // Filenames: bl=bottom left, b=bottom, br=bottom right, r=right, tr=top right - - // Normal Drop Shadow - private static final Image ShadowBottom = loadIcon("/icons/shadow-b.png"); - private static final Image ShadowBottomLeft = loadIcon("/icons/shadow-bl.png"); - private static final Image ShadowBottomRight = loadIcon("/icons/shadow-br.png"); - private static final Image ShadowRight = loadIcon("/icons/shadow-r.png"); - private static final Image ShadowTopRight = loadIcon("/icons/shadow-tr.png"); - private static final Image ShadowTopLeft = loadIcon("/icons/shadow-tl.png"); - private static final Image ShadowLeft = loadIcon("/icons/shadow-l.png"); - - // Small Drop Shadow - private static final Image Shadow2Bottom = loadIcon("/icons/shadow2-b.png"); - private static final Image Shadow2BottomLeft = loadIcon("/icons/shadow2-bl.png"); - private static final Image Shadow2BottomRight = loadIcon("/icons/shadow2-br.png"); - private static final Image Shadow2Right = loadIcon("/icons/shadow2-r.png"); - private static final Image Shadow2TopRight = loadIcon("/icons/shadow2-tr.png"); - private static final Image Shadow2TopLeft = loadIcon("/icons/shadow2-tl.png"); - private static final Image Shadow2Left = loadIcon("/icons/shadow2-l.png"); -} diff --git a/tools/layoutlib/bridge/src/android/view/SurfaceView.java b/tools/layoutlib/bridge/src/android/view/SurfaceView.java deleted file mode 100644 index ebb2af45320e..000000000000 --- a/tools/layoutlib/bridge/src/android/view/SurfaceView.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2006 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.view; - -import com.android.layoutlib.bridge.MockView; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Rect; -import android.graphics.Region; -import android.util.AttributeSet; - -/** - * Mock version of the SurfaceView. - * Only non override public methods from the real SurfaceView have been added in there. - * Methods that take an unknown class as parameter or as return object, have been removed for now. - * - * TODO: generate automatically. - * - */ -public class SurfaceView extends MockView { - - public SurfaceView(Context context) { - this(context, null); - } - - public SurfaceView(Context context, AttributeSet attrs) { - this(context, attrs , 0); - } - - public SurfaceView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - public SurfaceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - } - - public boolean gatherTransparentRegion(Region region) { - return false; - } - - public void setZOrderMediaOverlay(boolean isMediaOverlay) { - } - - public void setZOrderOnTop(boolean onTop) { - } - - public void setSecure(boolean isSecure) { - } - - public SurfaceHolder getHolder() { - return mSurfaceHolder; - } - - private SurfaceHolder mSurfaceHolder = new SurfaceHolder() { - - @Override - public boolean isCreating() { - return false; - } - - @Override - public void addCallback(Callback callback) { - } - - @Override - public void removeCallback(Callback callback) { - } - - @Override - public void setFixedSize(int width, int height) { - } - - @Override - public void setSizeFromLayout() { - } - - @Override - public void setFormat(int format) { - } - - @Override - public void setType(int type) { - } - - @Override - public void setKeepScreenOn(boolean screenOn) { - } - - @Override - public Canvas lockCanvas() { - return null; - } - - @Override - public Canvas lockCanvas(Rect dirty) { - return null; - } - - @Override - public void unlockCanvasAndPost(Canvas canvas) { - } - - @Override - public Surface getSurface() { - return null; - } - - @Override - public Rect getSurfaceFrame() { - return null; - } - }; -} - diff --git a/tools/layoutlib/bridge/src/android/view/ViewConfiguration_Accessor.java b/tools/layoutlib/bridge/src/android/view/ViewConfiguration_Accessor.java deleted file mode 100644 index c3533e0182c4..000000000000 --- a/tools/layoutlib/bridge/src/android/view/ViewConfiguration_Accessor.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2011 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.view; - -/** - * Class allowing access to package-protected methods/fields. - */ -public class ViewConfiguration_Accessor { - - public static void clearConfigurations() { - // clear the stored ViewConfiguration since the map is per density and not per context. - ViewConfiguration.sConfigurations.clear(); - } - -} diff --git a/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java b/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java deleted file mode 100644 index 4b760a7d4638..000000000000 --- a/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java +++ /dev/null @@ -1,158 +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.view; - -import com.android.resources.Density; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.graphics.Bitmap; -import android.graphics.Bitmap_Delegate; -import android.graphics.Canvas; -import android.graphics.Outline; -import android.graphics.Path_Delegate; -import android.graphics.Rect; -import android.graphics.Region.Op; -import android.view.animation.Transformation; - -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; - -/** - * Delegate used to provide new implementation of a select few methods of {@link ViewGroup} - * <p/> - * Through the layoutlib_create tool, the original methods of ViewGroup have been replaced by calls - * to methods of the same name in this delegate class. - */ -public class ViewGroup_Delegate { - - /** - * Overrides the original drawChild call in ViewGroup to draw the shadow. - */ - @LayoutlibDelegate - /*package*/ static boolean drawChild(ViewGroup thisVG, Canvas canvas, View child, - long drawingTime) { - if (child.getZ() > thisVG.getZ()) { - // The background's bounds are set lazily. Make sure they are set correctly so that - // the outline obtained is correct. - child.setBackgroundBounds(); - ViewOutlineProvider outlineProvider = child.getOutlineProvider(); - if (outlineProvider != null) { - Outline outline = child.mAttachInfo.mTmpOutline; - outlineProvider.getOutline(child, outline); - if (outline.mPath != null || (outline.mRect != null && !outline.mRect.isEmpty())) { - int restoreTo = transformCanvas(thisVG, canvas, child); - drawShadow(thisVG, canvas, child, outline); - canvas.restoreToCount(restoreTo); - } - } - } - return thisVG.drawChild_Original(canvas, child, drawingTime); - } - - private static void drawShadow(ViewGroup parent, Canvas canvas, View child, - Outline outline) { - float elevation = getElevation(child, parent); - if(outline.mMode == Outline.MODE_ROUND_RECT && outline.mRect != null) { - RectShadowPainter.paintShadow(outline, elevation, canvas); - return; - } - BufferedImage shadow = null; - if (outline.mPath != null) { - shadow = getPathShadow(outline, canvas, elevation); - } - if (shadow == null) { - return; - } - Bitmap bitmap = Bitmap_Delegate.createBitmap(shadow, false, - Density.getEnum(canvas.getDensity())); - Rect clipBounds = canvas.getClipBounds(); - Rect newBounds = new Rect(clipBounds); - newBounds.inset((int)-elevation, (int)-elevation); - canvas.clipRect(newBounds, Op.REPLACE); - canvas.drawBitmap(bitmap, 0, 0, null); - canvas.clipRect(clipBounds, Op.REPLACE); - } - - private static float getElevation(View child, ViewGroup parent) { - return child.getZ() - parent.getZ(); - } - - private static BufferedImage getPathShadow(Outline outline, Canvas canvas, float elevation) { - Rect clipBounds = canvas.getClipBounds(); - if (clipBounds.isEmpty()) { - return null; - } - BufferedImage image = new BufferedImage(clipBounds.width(), clipBounds.height(), - BufferedImage.TYPE_INT_ARGB); - Graphics2D graphics = image.createGraphics(); - graphics.draw(Path_Delegate.getDelegate(outline.mPath.mNativePath).getJavaShape()); - graphics.dispose(); - return ShadowPainter.createDropShadow(image, (int) elevation); - } - - // Copied from android.view.View#draw(Canvas, ViewGroup, long) and removed code paths - // which were never taken. Ideally, we should hook up the shadow code in the same method so - // that we don't have to transform the canvas twice. - private static int transformCanvas(ViewGroup thisVG, Canvas canvas, View child) { - final int restoreTo = canvas.save(); - final boolean childHasIdentityMatrix = child.hasIdentityMatrix(); - int flags = thisVG.mGroupFlags; - Transformation transformToApply = null; - boolean concatMatrix = false; - if ((flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) { - final Transformation t = thisVG.getChildTransformation(); - final boolean hasTransform = thisVG.getChildStaticTransformation(child, t); - if (hasTransform) { - final int transformType = t.getTransformationType(); - transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null; - concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0; - } - } - concatMatrix |= childHasIdentityMatrix; - - child.computeScroll(); - int sx = child.mScrollX; - int sy = child.mScrollY; - - canvas.translate(child.mLeft - sx, child.mTop - sy); - float alpha = child.getAlpha() * child.getTransitionAlpha(); - - if (transformToApply != null || alpha < 1 || !childHasIdentityMatrix) { - if (transformToApply != null || !childHasIdentityMatrix) { - int transX = -sx; - int transY = -sy; - - if (transformToApply != null) { - if (concatMatrix) { - // Undo the scroll translation, apply the transformation matrix, - // then redo the scroll translate to get the correct result. - canvas.translate(-transX, -transY); - canvas.concat(transformToApply.getMatrix()); - canvas.translate(transX, transY); - } - if (!childHasIdentityMatrix) { - canvas.translate(-transX, -transY); - canvas.concat(child.getMatrix()); - canvas.translate(transX, transY); - } - } - - } - } - return restoreTo; - } -} diff --git a/tools/layoutlib/bridge/src/android/view/ViewRootImpl_Accessor.java b/tools/layoutlib/bridge/src/android/view/ViewRootImpl_Accessor.java deleted file mode 100644 index 0e15b97243b0..000000000000 --- a/tools/layoutlib/bridge/src/android/view/ViewRootImpl_Accessor.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 android.view; - -/** - * Accessor to allow layoutlib to call {@link ViewRootImpl#dispatchApplyInsets} directly. - */ -public class ViewRootImpl_Accessor { - public static void dispatchApplyInsets(ViewRootImpl viewRoot, View host) { - viewRoot.dispatchApplyInsets(host); - } -} diff --git a/tools/layoutlib/bridge/src/android/view/ViewRootImpl_Delegate.java b/tools/layoutlib/bridge/src/android/view/ViewRootImpl_Delegate.java deleted file mode 100644 index 14b84ef5b20c..000000000000 --- a/tools/layoutlib/bridge/src/android/view/ViewRootImpl_Delegate.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2012 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.view; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate used to provide new implementation of a select few methods of {@link ViewRootImpl} - * - * Through the layoutlib_create tool, the original methods of ViewRootImpl have been replaced - * by calls to methods of the same name in this delegate class. - * - */ -public class ViewRootImpl_Delegate { - - @LayoutlibDelegate - /*package*/ static boolean isInTouchMode() { - return false; // this allows displaying selection. - } -} diff --git a/tools/layoutlib/bridge/src/android/view/View_Delegate.java b/tools/layoutlib/bridge/src/android/view/View_Delegate.java deleted file mode 100644 index 408ec54975ac..000000000000 --- a/tools/layoutlib/bridge/src/android/view/View_Delegate.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.view; - -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.content.Context; -import android.os.IBinder; - -/** - * Delegate used to provide new implementation of a select few methods of {@link View} - * - * Through the layoutlib_create tool, the original methods of View have been replaced - * by calls to methods of the same name in this delegate class. - * - */ -public class View_Delegate { - - @LayoutlibDelegate - /*package*/ static boolean isInEditMode(View thisView) { - return true; - } - - @LayoutlibDelegate - /*package*/ static IBinder getWindowToken(View thisView) { - Context baseContext = BridgeContext.getBaseContext(thisView.getContext()); - if (baseContext instanceof BridgeContext) { - return ((BridgeContext) baseContext).getBinder(); - } - return null; - } -} diff --git a/tools/layoutlib/bridge/src/android/view/WindowCallback.java b/tools/layoutlib/bridge/src/android/view/WindowCallback.java deleted file mode 100644 index 1ea8a9f2294e..000000000000 --- a/tools/layoutlib/bridge/src/android/view/WindowCallback.java +++ /dev/null @@ -1,144 +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.view; - -import android.annotation.Nullable; -import android.view.ActionMode.Callback; -import android.view.WindowManager.LayoutParams; -import android.view.accessibility.AccessibilityEvent; - -import java.util.List; - -/** - * An empty implementation of {@link Window.Callback} that always returns null/false. - */ -public class WindowCallback implements Window.Callback { - @Override - public boolean dispatchKeyEvent(KeyEvent event) { - return false; - } - - @Override - public boolean dispatchKeyShortcutEvent(KeyEvent event) { - return false; - } - - @Override - public boolean dispatchTouchEvent(MotionEvent event) { - return false; - } - - @Override - public boolean dispatchTrackballEvent(MotionEvent event) { - return false; - } - - @Override - public boolean dispatchGenericMotionEvent(MotionEvent event) { - return false; - } - - @Override - public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { - return false; - } - - @Override - public View onCreatePanelView(int featureId) { - return null; - } - - @Override - public boolean onCreatePanelMenu(int featureId, Menu menu) { - return false; - } - - @Override - public boolean onPreparePanel(int featureId, View view, Menu menu) { - return false; - } - - @Override - public boolean onMenuOpened(int featureId, Menu menu) { - return false; - } - - @Override - public boolean onMenuItemSelected(int featureId, MenuItem item) { - return false; - } - - @Override - public void onWindowAttributesChanged(LayoutParams attrs) { - - } - - @Override - public void onContentChanged() { - - } - - @Override - public void onWindowFocusChanged(boolean hasFocus) { - - } - - @Override - public void onAttachedToWindow() { - - } - - @Override - public void onDetachedFromWindow() { - - } - - @Override - public void onPanelClosed(int featureId, Menu menu) { - - } - - @Override - public boolean onSearchRequested(SearchEvent searchEvent) { - return onSearchRequested(); - } - - @Override - public boolean onSearchRequested() { - return false; - } - - @Override - public ActionMode onWindowStartingActionMode(Callback callback) { - return null; - } - - @Override - public ActionMode onWindowStartingActionMode(Callback callback, int type) { - return null; - } - - @Override - public void onActionModeStarted(ActionMode mode) { - - } - - @Override - public void onActionModeFinished(ActionMode mode) { - - } -} diff --git a/tools/layoutlib/bridge/src/android/view/WindowManagerGlobal_Delegate.java b/tools/layoutlib/bridge/src/android/view/WindowManagerGlobal_Delegate.java deleted file mode 100644 index 2606e55e5dbe..000000000000 --- a/tools/layoutlib/bridge/src/android/view/WindowManagerGlobal_Delegate.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2012 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.view; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate used to provide new implementation of a select few methods of - * {@link WindowManagerGlobal} - * - * Through the layoutlib_create tool, the original methods of WindowManagerGlobal have been - * replaced by calls to methods of the same name in this delegate class. - * - */ -public class WindowManagerGlobal_Delegate { - - private static IWindowManager sService; - - @LayoutlibDelegate - public static IWindowManager getWindowManagerService() { - return sService; - } - - // ---- internal implementation stuff ---- - - public static void setWindowManagerService(IWindowManager service) { - sService = service; - } -} diff --git a/tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java b/tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java deleted file mode 100644 index 11cb046aa2f8..000000000000 --- a/tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Copyright (C) 2009 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.view.accessibility; - -import android.accessibilityservice.AccessibilityServiceInfo; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.content.pm.ServiceInfo; -import android.os.Handler; -import android.view.IWindow; -import android.view.View; - -import java.util.Collections; -import java.util.List; - -/** - * System level service that serves as an event dispatch for {@link AccessibilityEvent}s. - * Such events are generated when something notable happens in the user interface, - * for example an {@link android.app.Activity} starts, the focus or selection of a - * {@link android.view.View} changes etc. Parties interested in handling accessibility - * events implement and register an accessibility service which extends - * {@code android.accessibilityservice.AccessibilityService}. - * - * @see AccessibilityEvent - * @see android.content.Context#getSystemService - */ -@SuppressWarnings("UnusedDeclaration") -public final class AccessibilityManager { - - private static AccessibilityManager sInstance = new AccessibilityManager(null, null, 0); - - - /** - * Listener for the accessibility state. - */ - public interface AccessibilityStateChangeListener { - - /** - * Called back on change in the accessibility state. - * - * @param enabled Whether accessibility is enabled. - */ - public void onAccessibilityStateChanged(boolean enabled); - } - - /** - * Listener for the system touch exploration state. To listen for changes to - * the touch exploration state on the device, implement this interface and - * register it with the system by calling - * {@link #addTouchExplorationStateChangeListener}. - */ - public interface TouchExplorationStateChangeListener { - - /** - * Called when the touch exploration enabled state changes. - * - * @param enabled Whether touch exploration is enabled. - */ - public void onTouchExplorationStateChanged(boolean enabled); - } - - /** - * Listener for the system high text contrast state. To listen for changes to - * the high text contrast state on the device, implement this interface and - * register it with the system by calling - * {@link #addHighTextContrastStateChangeListener}. - */ - public interface HighTextContrastChangeListener { - - /** - * Called when the high text contrast enabled state changes. - * - * @param enabled Whether high text contrast is enabled. - */ - public void onHighTextContrastStateChanged(boolean enabled); - } - - private final IAccessibilityManagerClient.Stub mClient = - new IAccessibilityManagerClient.Stub() { - public void setState(int state) { - } - - public void notifyServicesStateChanged() { - } - - public void setRelevantEventTypes(int eventTypes) { - } - }; - - /** - * Get an AccessibilityManager instance (create one if necessary). - * - */ - public static AccessibilityManager getInstance(Context context) { - return sInstance; - } - - /** - * Create an instance. - * - * @param context A {@link Context}. - */ - public AccessibilityManager(Context context, IAccessibilityManager service, int userId) { - } - - public IAccessibilityManagerClient getClient() { - return mClient; - } - - /** - * Returns if the {@link AccessibilityManager} is enabled. - * - * @return True if this {@link AccessibilityManager} is enabled, false otherwise. - */ - public boolean isEnabled() { - return false; - } - - /** - * Returns if the touch exploration in the system is enabled. - * - * @return True if touch exploration is enabled, false otherwise. - */ - public boolean isTouchExplorationEnabled() { - return true; - } - - /** - * Returns if the high text contrast in the system is enabled. - * <p> - * <strong>Note:</strong> You need to query this only if you application is - * doing its own rendering and does not rely on the platform rendering pipeline. - * </p> - * - */ - public boolean isHighTextContrastEnabled() { - return false; - } - - /** - * Sends an {@link AccessibilityEvent}. - */ - public void sendAccessibilityEvent(AccessibilityEvent event) { - } - - /** - * Requests interruption of the accessibility feedback from all accessibility services. - */ - public void interrupt() { - } - - /** - * Returns the {@link ServiceInfo}s of the installed accessibility services. - * - * @return An unmodifiable list with {@link ServiceInfo}s. - */ - @Deprecated - public List<ServiceInfo> getAccessibilityServiceList() { - return Collections.emptyList(); - } - - public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList() { - return Collections.emptyList(); - } - - /** - * Returns the {@link AccessibilityServiceInfo}s of the enabled accessibility services - * for a given feedback type. - * - * @param feedbackTypeFlags The feedback type flags. - * @return An unmodifiable list with {@link AccessibilityServiceInfo}s. - * - * @see AccessibilityServiceInfo#FEEDBACK_AUDIBLE - * @see AccessibilityServiceInfo#FEEDBACK_GENERIC - * @see AccessibilityServiceInfo#FEEDBACK_HAPTIC - * @see AccessibilityServiceInfo#FEEDBACK_SPOKEN - * @see AccessibilityServiceInfo#FEEDBACK_VISUAL - */ - public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList( - int feedbackTypeFlags) { - return Collections.emptyList(); - } - - /** - * Registers an {@link AccessibilityStateChangeListener} for changes in - * the global accessibility state of the system. - * - * @param listener The listener. - * @return True if successfully registered. - */ - public boolean addAccessibilityStateChangeListener( - AccessibilityStateChangeListener listener) { - return true; - } - - /** - * Registers an {@link AccessibilityStateChangeListener} for changes in - * the global accessibility state of the system. If the listener has already been registered, - * the handler used to call it back is updated. - * - * @param listener The listener. - * @param handler The handler on which the listener should be called back, or {@code null} - * for a callback on the process's main handler. - */ - public void addAccessibilityStateChangeListener( - @NonNull AccessibilityStateChangeListener listener, @Nullable Handler handler) {} - - public boolean removeAccessibilityStateChangeListener( - AccessibilityStateChangeListener listener) { - return true; - } - - /** - * Registers a {@link TouchExplorationStateChangeListener} for changes in - * the global touch exploration state of the system. - * - * @param listener The listener. - * @return True if successfully registered. - */ - public boolean addTouchExplorationStateChangeListener( - @NonNull TouchExplorationStateChangeListener listener) { - return true; - } - - /** - * Registers an {@link TouchExplorationStateChangeListener} for changes in - * the global touch exploration state of the system. If the listener has already been - * registered, the handler used to call it back is updated. - * - * @param listener The listener. - * @param handler The handler on which the listener should be called back, or {@code null} - * for a callback on the process's main handler. - */ - public void addTouchExplorationStateChangeListener( - @NonNull TouchExplorationStateChangeListener listener, @Nullable Handler handler) {} - - /** - * Unregisters a {@link TouchExplorationStateChangeListener}. - * - * @param listener The listener. - * @return True if successfully unregistered. - */ - public boolean removeTouchExplorationStateChangeListener( - @NonNull TouchExplorationStateChangeListener listener) { - return true; - } - - /** - * Registers a {@link HighTextContrastChangeListener} for changes in - * the global high text contrast state of the system. - * - * @param listener The listener. - * - * @hide - */ - public void addHighTextContrastStateChangeListener( - @NonNull HighTextContrastChangeListener listener, @Nullable Handler handler) {} - - /** - * Unregisters a {@link HighTextContrastChangeListener}. - * - * @param listener The listener. - * - * @hide - */ - public void removeHighTextContrastStateChangeListener( - @NonNull HighTextContrastChangeListener listener) {} - - /** - * Sets the current state and notifies listeners, if necessary. - * - * @param stateFlags The state flags. - */ - private void setStateLocked(int stateFlags) { - } - - public int addAccessibilityInteractionConnection(IWindow windowToken, - IAccessibilityInteractionConnection connection) { - return View.NO_ID; - } - - public void removeAccessibilityInteractionConnection(IWindow windowToken) { - } - -} diff --git a/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Accessor.java b/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Accessor.java deleted file mode 100644 index dc4f9c868185..000000000000 --- a/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Accessor.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2011 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.view.inputmethod; - -/** - * Class allowing access to package-protected methods/fields. - */ -public class InputMethodManager_Accessor { - - public static void resetInstance() { - InputMethodManager.sInstance = null; - } -} diff --git a/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java b/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java deleted file mode 100644 index 7c98847a4cf3..000000000000 --- a/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2011 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.view.inputmethod; - -import com.android.layoutlib.bridge.android.BridgeIInputMethodManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.content.Context; -import android.os.Looper; - - -/** - * Delegate used to provide new implementation of a select few methods of {@link InputMethodManager} - * - * Through the layoutlib_create tool, the original methods of InputMethodManager have been replaced - * by calls to methods of the same name in this delegate class. - * - */ -public class InputMethodManager_Delegate { - - // ---- Overridden methods ---- - - @LayoutlibDelegate - /*package*/ static InputMethodManager getInstance() { - synchronized (InputMethodManager.class) { - InputMethodManager imm = InputMethodManager.peekInstance(); - if (imm == null) { - imm = new InputMethodManager( - new BridgeIInputMethodManager(), Looper.getMainLooper()); - InputMethodManager.sInstance = imm; - } - return imm; - } - } -} diff --git a/tools/layoutlib/bridge/src/android/view/textservice/TextServicesManager.java b/tools/layoutlib/bridge/src/android/view/textservice/TextServicesManager.java deleted file mode 100644 index 8e1f21831a35..000000000000 --- a/tools/layoutlib/bridge/src/android/view/textservice/TextServicesManager.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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 android.view.textservice; - -import android.os.Bundle; -import android.view.textservice.SpellCheckerSession.SpellCheckerSessionListener; - -import java.util.Locale; - -/** - * A stub class of TextServicesManager for Layout-Lib. - */ -public final class TextServicesManager { - private static final TextServicesManager sInstance = new TextServicesManager(); - private static final SpellCheckerInfo[] EMPTY_SPELL_CHECKER_INFO = new SpellCheckerInfo[0]; - - /** - * Retrieve the global TextServicesManager instance, creating it if it doesn't already exist. - * @hide - */ - public static TextServicesManager getInstance() { - return sInstance; - } - - public SpellCheckerSession newSpellCheckerSession(Bundle bundle, Locale locale, - SpellCheckerSessionListener listener, boolean referToSpellCheckerLanguageSettings) { - return null; - } - - /** - * @hide - */ - public SpellCheckerInfo[] getEnabledSpellCheckers() { - return EMPTY_SPELL_CHECKER_INFO; - } - - /** - * @hide - */ - public SpellCheckerInfo getCurrentSpellChecker() { - return null; - } - - /** - * @hide - */ - public SpellCheckerSubtype getCurrentSpellCheckerSubtype( - boolean allowImplicitlySelectedSubtype) { - return null; - } - - /** - * @hide - */ - public boolean isSpellCheckerEnabled() { - return false; - } -} diff --git a/tools/layoutlib/bridge/src/android/webkit/WebView.java b/tools/layoutlib/bridge/src/android/webkit/WebView.java deleted file mode 100644 index 202f2046a3fd..000000000000 --- a/tools/layoutlib/bridge/src/android/webkit/WebView.java +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.webkit; - -import com.android.layoutlib.bridge.MockView; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Picture; -import android.os.Bundle; -import android.os.Message; -import android.util.AttributeSet; -import android.view.View; - -/** - * Mock version of the WebView. - * Only non override public methods from the real WebView have been added in there. - * Methods that take an unknown class as parameter or as return object, have been removed for now. - * - * TODO: generate automatically. - * - */ -public class WebView extends MockView { - - /** - * Construct a new WebView with a Context object. - * @param context A Context object used to access application assets. - */ - public WebView(Context context) { - this(context, null); - } - - /** - * Construct a new WebView with layout parameters. - * @param context A Context object used to access application assets. - * @param attrs An AttributeSet passed to our parent. - */ - public WebView(Context context, AttributeSet attrs) { - this(context, attrs, com.android.internal.R.attr.webViewStyle); - } - - /** - * Construct a new WebView with layout parameters and a default style. - * @param context A Context object used to access application assets. - * @param attrs An AttributeSet passed to our parent. - * @param defStyle The default style resource ID. - */ - public WebView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - // START FAKE PUBLIC METHODS - - public void setHorizontalScrollbarOverlay(boolean overlay) { - } - - public void setVerticalScrollbarOverlay(boolean overlay) { - } - - public boolean overlayHorizontalScrollbar() { - return false; - } - - public boolean overlayVerticalScrollbar() { - return false; - } - - public void savePassword(String host, String username, String password) { - } - - public void setHttpAuthUsernamePassword(String host, String realm, - String username, String password) { - } - - public String[] getHttpAuthUsernamePassword(String host, String realm) { - return null; - } - - public void destroy() { - } - - public static void enablePlatformNotifications() { - } - - public static void disablePlatformNotifications() { - } - - public void loadUrl(String url) { - } - - public void loadData(String data, String mimeType, String encoding) { - } - - public void loadDataWithBaseURL(String baseUrl, String data, - String mimeType, String encoding, String failUrl) { - } - - public void stopLoading() { - } - - public void reload() { - } - - public boolean canGoBack() { - return false; - } - - public void goBack() { - } - - public boolean canGoForward() { - return false; - } - - public void goForward() { - } - - public boolean canGoBackOrForward(int steps) { - return false; - } - - public void goBackOrForward(int steps) { - } - - public boolean pageUp(boolean top) { - return false; - } - - public boolean pageDown(boolean bottom) { - return false; - } - - public void clearView() { - } - - public Picture capturePicture() { - return null; - } - - public float getScale() { - return 0; - } - - public void setInitialScale(int scaleInPercent) { - } - - public void invokeZoomPicker() { - } - - public void requestFocusNodeHref(Message hrefMsg) { - } - - public void requestImageRef(Message msg) { - } - - public String getUrl() { - return null; - } - - public String getTitle() { - return null; - } - - public Bitmap getFavicon() { - return null; - } - - public int getProgress() { - return 0; - } - - public int getContentHeight() { - return 0; - } - - public void pauseTimers() { - } - - public void resumeTimers() { - } - - public void clearCache() { - } - - public void clearFormData() { - } - - public void clearHistory() { - } - - public void clearSslPreferences() { - } - - public static String findAddress(String addr) { - return null; - } - - public void documentHasImages(Message response) { - } - - public void setWebViewClient(WebViewClient client) { - } - - public void setDownloadListener(DownloadListener listener) { - } - - public void setWebChromeClient(WebChromeClient client) { - } - - public void addJavascriptInterface(Object obj, String interfaceName) { - } - - public View getZoomControls() { - return null; - } - - public boolean zoomIn() { - return false; - } - - public boolean zoomOut() { - return false; - } -} diff --git a/tools/layoutlib/bridge/src/android/widget/Toolbar_Accessor.java b/tools/layoutlib/bridge/src/android/widget/Toolbar_Accessor.java deleted file mode 100644 index fdd1779d6bd3..000000000000 --- a/tools/layoutlib/bridge/src/android/widget/Toolbar_Accessor.java +++ /dev/null @@ -1,32 +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 android.content.Context; - -/** - * To access non public members of classes in {@link Toolbar} - */ -public class Toolbar_Accessor { - public static ActionMenuPresenter getActionMenuPresenter(Toolbar toolbar) { - return toolbar.getOuterActionMenuPresenter(); - } - - public static Context getPopupContext(Toolbar toolbar) { - return toolbar.getPopupContext(); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/internal/util/VirtualRefBasePtr_Delegate.java b/tools/layoutlib/bridge/src/com/android/internal/util/VirtualRefBasePtr_Delegate.java deleted file mode 100644 index 01fe45d2644c..000000000000 --- a/tools/layoutlib/bridge/src/com/android/internal/util/VirtualRefBasePtr_Delegate.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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 com.android.internal.util; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.util.LongSparseLongArray; - -/** - * Delegate used to provide new implementation the native methods of {@link VirtualRefBasePtr} - * - * Through the layoutlib_create tool, the original native methods of VirtualRefBasePtr have been - * replaced by calls to methods of the same name in this delegate class. - * - */ -@SuppressWarnings("unused") -public class VirtualRefBasePtr_Delegate { - private static final DelegateManager<Object> sManager = new DelegateManager<>(Object.class); - private static final LongSparseLongArray sRefCount = new LongSparseLongArray(); - - @LayoutlibDelegate - /*package*/ static synchronized void nIncStrong(long ptr) { - long counter = sRefCount.get(ptr); - sRefCount.put(ptr, ++counter); - } - - @LayoutlibDelegate - /*package*/ static synchronized void nDecStrong(long ptr) { - long counter = sRefCount.get(ptr); - - if (counter > 1) { - sRefCount.put(ptr, --counter); - } else { - sRefCount.delete(ptr); - sManager.removeJavaReferenceFor(ptr); - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/internal/util/XmlUtils_Delegate.java b/tools/layoutlib/bridge/src/com/android/internal/util/XmlUtils_Delegate.java deleted file mode 100644 index bf998b8737cd..000000000000 --- a/tools/layoutlib/bridge/src/com/android/internal/util/XmlUtils_Delegate.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.util; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - - -/** - * Delegate used to provide new implementation of a select few methods of {@link XmlUtils} - * - * Through the layoutlib_create tool, the original methods of XmlUtils have been replaced - * by calls to methods of the same name in this delegate class. - * - */ -public class XmlUtils_Delegate { - - @LayoutlibDelegate - /*package*/ static final int convertValueToInt(CharSequence charSeq, int defaultValue) { - if (null == charSeq) - return defaultValue; - - String nm = charSeq.toString(); - - // This code is copied from the original implementation. The issue is that - // The Dalvik libraries are able to handle Integer.parse("XXXXXXXX", 16) where XXXXXXX - // is > 80000000 but the Java VM cannot. - - int sign = 1; - int index = 0; - int len = nm.length(); - int base = 10; - - if ('-' == nm.charAt(0)) { - sign = -1; - index++; - } - - if ('0' == nm.charAt(index)) { - // Quick check for a zero by itself - if (index == (len - 1)) - return 0; - - char c = nm.charAt(index + 1); - - if ('x' == c || 'X' == c) { - index += 2; - base = 16; - } else { - index++; - base = 8; - } - } - else if ('#' == nm.charAt(index)) { - index++; - base = 16; - } - - return ((int)Long.parseLong(nm.substring(index), base)) * sign; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/internal/view/animation/NativeInterpolatorFactoryHelper_Delegate.java b/tools/layoutlib/bridge/src/com/android/internal/view/animation/NativeInterpolatorFactoryHelper_Delegate.java deleted file mode 100644 index da1ab27b6ff2..000000000000 --- a/tools/layoutlib/bridge/src/com/android/internal/view/animation/NativeInterpolatorFactoryHelper_Delegate.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * 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 com.android.internal.view.animation; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.graphics.Path; -import android.util.MathUtils; -import android.view.animation.AccelerateDecelerateInterpolator; -import android.view.animation.AccelerateInterpolator; -import android.view.animation.AnticipateInterpolator; -import android.view.animation.AnticipateOvershootInterpolator; -import android.view.animation.BaseInterpolator; -import android.view.animation.BounceInterpolator; -import android.view.animation.CycleInterpolator; -import android.view.animation.DecelerateInterpolator; -import android.view.animation.Interpolator; -import android.view.animation.LinearInterpolator; -import android.view.animation.OvershootInterpolator; -import android.view.animation.PathInterpolator; - -/** - * Delegate used to provide new implementation of a select few methods of {@link - * NativeInterpolatorFactoryHelper} - * <p> - * Through the layoutlib_create tool, the original methods of NativeInterpolatorFactoryHelper have - * been replaced by calls to methods of the same name in this delegate class. - */ -@SuppressWarnings("unused") -public class NativeInterpolatorFactoryHelper_Delegate { - private static final DelegateManager<Interpolator> sManager = new DelegateManager<> - (Interpolator.class); - - public static Interpolator getDelegate(long nativePtr) { - return sManager.getDelegate(nativePtr); - } - - @LayoutlibDelegate - /*package*/ static long createAccelerateDecelerateInterpolator() { - return sManager.addNewDelegate(new AccelerateDecelerateInterpolator()); - } - - @LayoutlibDelegate - /*package*/ static long createAccelerateInterpolator(float factor) { - return sManager.addNewDelegate(new AccelerateInterpolator(factor)); - } - - @LayoutlibDelegate - /*package*/ static long createAnticipateInterpolator(float tension) { - return sManager.addNewDelegate(new AnticipateInterpolator(tension)); - } - - @LayoutlibDelegate - /*package*/ static long createAnticipateOvershootInterpolator(float tension) { - return sManager.addNewDelegate(new AnticipateOvershootInterpolator(tension)); - } - - @LayoutlibDelegate - /*package*/ static long createBounceInterpolator() { - return sManager.addNewDelegate(new BounceInterpolator()); - } - - @LayoutlibDelegate - /*package*/ static long createCycleInterpolator(float cycles) { - return sManager.addNewDelegate(new CycleInterpolator(cycles)); - } - - @LayoutlibDelegate - /*package*/ static long createDecelerateInterpolator(float factor) { - return sManager.addNewDelegate(new DecelerateInterpolator(factor)); - } - - @LayoutlibDelegate - /*package*/ static long createLinearInterpolator() { - return sManager.addNewDelegate(new LinearInterpolator()); - } - - @LayoutlibDelegate - /*package*/ static long createOvershootInterpolator(float tension) { - return sManager.addNewDelegate(new OvershootInterpolator(tension)); - } - - @LayoutlibDelegate - /*package*/ static long createPathInterpolator(float[] x, float[] y) { - Path path = new Path(); - path.moveTo(x[0], y[0]); - for (int i = 1; i < x.length; i++) { - path.lineTo(x[i], y[i]); - } - return sManager.addNewDelegate(new PathInterpolator(path)); - } - - private static class LutInterpolator extends BaseInterpolator { - private final float[] mValues; - private final int mSize; - - private LutInterpolator(float[] values) { - mValues = values; - mSize = mValues.length; - } - - @Override - public float getInterpolation(float input) { - float lutpos = input * (mSize - 1); - if (lutpos >= (mSize - 1)) { - return mValues[mSize - 1]; - } - - int ipart = (int) lutpos; - float weight = lutpos - ipart; - - int i1 = ipart; - int i2 = Math.min(i1 + 1, mSize - 1); - - assert i1 >= 0 && i2 >= 0 : "Negatives in the interpolation"; - - return MathUtils.lerp(mValues[i1], mValues[i2], weight); - } - } - - @LayoutlibDelegate - /*package*/ static long createLutInterpolator(float[] values) { - return sManager.addNewDelegate(new LutInterpolator(values)); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/internal/view/menu/BridgeMenuItemImpl.java b/tools/layoutlib/bridge/src/com/android/internal/view/menu/BridgeMenuItemImpl.java deleted file mode 100644 index bb95c4e35398..000000000000 --- a/tools/layoutlib/bridge/src/com/android/internal/view/menu/BridgeMenuItemImpl.java +++ /dev/null @@ -1,65 +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 com.android.internal.view.menu; - -import com.android.layoutlib.bridge.android.BridgeContext; - -import android.content.Context; -import android.view.View; - -/** - * An extension of the {@link MenuItemImpl} to store the view cookie also. - */ -public class BridgeMenuItemImpl extends MenuItemImpl { - - /** - * An object returned by the IDE that helps mapping each View to the corresponding XML tag in - * the layout. For Menus, we store this cookie here and attach it to the corresponding view - * at the time of rendering. - */ - private Object viewCookie; - private BridgeContext mContext; - - /** - * Instantiates this menu item. - */ - BridgeMenuItemImpl(MenuBuilder menu, int group, int id, int categoryOrder, int ordering, - CharSequence title, int showAsAction) { - super(menu, group, id, categoryOrder, ordering, title, showAsAction); - Context context = menu.getContext(); - context = BridgeContext.getBaseContext(context); - if (context instanceof BridgeContext) { - mContext = ((BridgeContext) context); - } - } - - public Object getViewCookie() { - return viewCookie; - } - - public void setViewCookie(Object viewCookie) { - // If the menu item has an associated action provider view, - // directly set the cookie in the view to cookie map stored in BridgeContext. - View actionView = getActionView(); - if (actionView != null && mContext != null) { - mContext.addViewKey(actionView, viewCookie); - // We don't need to add the view cookie to the this item now. But there's no harm in - // storing it, in case we need it in the future. - } - this.viewCookie = viewCookie; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/internal/view/menu/MenuBuilder_Delegate.java b/tools/layoutlib/bridge/src/com/android/internal/view/menu/MenuBuilder_Delegate.java deleted file mode 100644 index 505fb8172ceb..000000000000 --- a/tools/layoutlib/bridge/src/com/android/internal/view/menu/MenuBuilder_Delegate.java +++ /dev/null @@ -1,38 +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 com.android.internal.view.menu; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate used to provide new implementation of a select few methods of {@link MenuBuilder} - * <p/> - * Through the layoutlib_create tool, the original methods of {@code MenuBuilder} have been - * replaced by calls to methods of the same name in this delegate class. - */ -public class MenuBuilder_Delegate { - /** - * The method overrides the instantiation of the {@link MenuItemImpl} with an instance of - * {@link BridgeMenuItemImpl} so that view cookies may be stored. - */ - @LayoutlibDelegate - /*package*/ static MenuItemImpl createNewMenuItem(MenuBuilder thisMenu, int group, int id, - int categoryOrder, int ordering, CharSequence title, int defaultShowAsAction) { - return new BridgeMenuItemImpl(thisMenu, group, id, categoryOrder, ordering, title, - defaultShowAsAction); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/internal/widget/ActionBarAccessor.java b/tools/layoutlib/bridge/src/com/android/internal/widget/ActionBarAccessor.java deleted file mode 100644 index 40b6220cf8a0..000000000000 --- a/tools/layoutlib/bridge/src/com/android/internal/widget/ActionBarAccessor.java +++ /dev/null @@ -1,32 +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 com.android.internal.widget; - -import android.widget.ActionMenuPresenter; - -/** - * To access non public members of AbsActionBarView - */ -public class ActionBarAccessor { - - /** - * Returns the {@link ActionMenuPresenter} associated with the {@link AbsActionBarView} - */ - public static ActionMenuPresenter getActionMenuPresenter(AbsActionBarView view) { - return view.mActionMenuPresenter; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java deleted file mode 100644 index 93fd005ebc05..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java +++ /dev/null @@ -1,670 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge; - -import com.android.ide.common.rendering.api.Capability; -import com.android.ide.common.rendering.api.DrawableParams; -import com.android.ide.common.rendering.api.Features; -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.ide.common.rendering.api.RenderSession; -import com.android.ide.common.rendering.api.Result; -import com.android.ide.common.rendering.api.Result.Status; -import com.android.ide.common.rendering.api.SessionParams; -import com.android.layoutlib.bridge.android.RenderParamsFlags; -import com.android.layoutlib.bridge.impl.RenderDrawable; -import com.android.layoutlib.bridge.impl.RenderSessionImpl; -import com.android.layoutlib.bridge.util.DynamicIdMap; -import com.android.ninepatch.NinePatchChunk; -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 android.annotation.NonNull; -import android.content.res.BridgeAssetManager; -import android.graphics.Bitmap; -import android.graphics.FontFamily_Delegate; -import android.graphics.Typeface; -import android.graphics.Typeface_Delegate; -import android.icu.util.ULocale; -import android.os.Looper; -import android.os.Looper_Accessor; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewParent; - -import java.io.File; -import java.lang.ref.SoftReference; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.EnumMap; -import java.util.EnumSet; -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; - -/** - * Main entry point of the LayoutLib Bridge. - * <p/>To use this bridge, simply instantiate an object of type {@link Bridge} and call - * {@link #createSession(SessionParams)} - */ -public final class Bridge extends com.android.ide.common.rendering.api.Bridge { - - private static final String ICU_LOCALE_DIRECTION_RTL = "right-to-left"; - - public static class StaticMethodNotImplementedException extends RuntimeException { - private static final long serialVersionUID = 1L; - - public StaticMethodNotImplementedException(String msg) { - super(msg); - } - } - - /** - * Lock to ensure only one rendering/inflating happens at a time. - * This is due to some singleton in the Android framework. - */ - private final static ReentrantLock sLock = new ReentrantLock(); - - /** - * Maps from id to resource type/name. This is for com.android.internal.R - */ - @SuppressWarnings("deprecation") - private final static Map<Integer, Pair<ResourceType, String>> sRMap = new HashMap<>(); - - /** - * Reverse map compared to sRMap, resource type -> (resource name -> id). - * This is for com.android.internal.R. - */ - private final static Map<ResourceType, Map<String, Integer>> sRevRMap = new EnumMap<>(ResourceType.class); - - // framework resources are defined as 0x01XX#### where XX is the resource type (layout, - // drawable, etc...). Using FF as the type allows for 255 resource types before we get a - // collision which should be fine. - private final static int DYNAMIC_ID_SEED_START = 0x01ff0000; - private final static DynamicIdMap sDynamicIds = new DynamicIdMap(DYNAMIC_ID_SEED_START); - - private final static Map<Object, Map<String, SoftReference<Bitmap>>> sProjectBitmapCache = - new HashMap<>(); - private final static Map<Object, Map<String, SoftReference<NinePatchChunk>>> sProject9PatchCache = - - new HashMap<>(); - - private final static Map<String, SoftReference<Bitmap>> sFrameworkBitmapCache = new HashMap<>(); - private final static Map<String, SoftReference<NinePatchChunk>> sFramework9PatchCache = - new HashMap<>(); - - private static Map<String, Map<String, Integer>> sEnumValueMap; - private static Map<String, String> sPlatformProperties; - - /** - * A default log than prints to stdout/stderr. - */ - private final static LayoutLog sDefaultLog = new LayoutLog() { - @Override - public void error(String tag, String message, Object data) { - System.err.println(message); - } - - @Override - public void error(String tag, String message, Throwable throwable, Object data) { - System.err.println(message); - } - - @Override - public void warning(String tag, String message, Object data) { - System.out.println(message); - } - }; - - /** - * Current log. - */ - private static LayoutLog sCurrentLog = sDefaultLog; - - private static final int LAST_SUPPORTED_FEATURE = Features.THEME_PREVIEW_NAVIGATION_BAR; - - @Override - public int getApiLevel() { - return com.android.ide.common.rendering.api.Bridge.API_CURRENT; - } - - @SuppressWarnings("deprecation") - @Override - @Deprecated - public EnumSet<Capability> getCapabilities() { - // The Capability class is deprecated and frozen. All Capabilities enumerated there are - // supported by this version of LayoutLibrary. So, it's safe to use EnumSet.allOf() - return EnumSet.allOf(Capability.class); - } - - @Override - public boolean supports(int feature) { - return feature <= LAST_SUPPORTED_FEATURE; - } - - @Override - public boolean init(Map<String,String> platformProperties, - File fontLocation, - Map<String, Map<String, Integer>> enumValueMap, - LayoutLog log) { - sPlatformProperties = platformProperties; - sEnumValueMap = enumValueMap; - - BridgeAssetManager.initSystem(); - - // When DEBUG_LAYOUT is set and is not 0 or false, setup a default listener - // on static (native) methods which prints the signature on the console and - // throws an exception. - // This is useful when testing the rendering in ADT to identify static native - // methods that are ignored -- layoutlib_create makes them returns 0/false/null - // which is generally OK yet might be a problem, so this is how you'd find out. - // - // Currently layoutlib_create only overrides static native method. - // Static non-natives are not overridden and thus do not get here. - final String debug = System.getenv("DEBUG_LAYOUT"); - if (debug != null && !debug.equals("0") && !debug.equals("false")) { - - OverrideMethod.setDefaultListener(new MethodAdapter() { - @Override - public void onInvokeV(String signature, boolean isNative, Object caller) { - sDefaultLog.error(null, "Missing Stub: " + signature + - (isNative ? " (native)" : ""), null /*data*/); - - if (debug.equalsIgnoreCase("throw")) { - // Throwing this exception doesn't seem that useful. It breaks - // the layout editor yet doesn't display anything meaningful to the - // user. Having the error in the console is just as useful. We'll - // throw it only if the environment variable is "throw" or "THROW". - throw new StaticMethodNotImplementedException(signature); - } - } - }); - } - - // load the fonts. - FontFamily_Delegate.setFontLocation(fontLocation.getAbsolutePath()); - MemoryMappedFile_Delegate.setDataDir(fontLocation.getAbsoluteFile().getParentFile()); - - // now parse com.android.internal.R (and only this one as android.R is a subset of - // the internal version), and put the content in the maps. - try { - Class<?> r = com.android.internal.R.class; - // Parse the styleable class first, since it may contribute to attr values. - parseStyleable(); - - for (Class<?> inner : r.getDeclaredClasses()) { - if (inner == com.android.internal.R.styleable.class) { - // Already handled the styleable case. Not skipping attr, as there may be attrs - // that are not referenced from styleables. - continue; - } - String resTypeName = inner.getSimpleName(); - ResourceType resType = ResourceType.getEnum(resTypeName); - if (resType != null) { - Map<String, Integer> fullMap = null; - switch (resType) { - case ATTR: - fullMap = sRevRMap.get(ResourceType.ATTR); - break; - case STRING: - case STYLE: - // Slightly less than thousand entries in each. - fullMap = new HashMap<>(1280); - // no break. - default: - if (fullMap == null) { - fullMap = new HashMap<>(); - } - sRevRMap.put(resType, fullMap); - } - - for (Field f : inner.getDeclaredFields()) { - // only process static final fields. Since the final attribute may have - // been altered by layoutlib_create, we only check static - if (!isValidRField(f)) { - continue; - } - Class<?> type = f.getType(); - if (!type.isArray()) { - Integer value = (Integer) f.get(null); - //noinspection deprecation - sRMap.put(value, Pair.of(resType, f.getName())); - fullMap.put(f.getName(), value); - } - } - } - } - } catch (Exception throwable) { - if (log != null) { - log.error(LayoutLog.TAG_BROKEN, - "Failed to load com.android.internal.R from the layout library jar", - throwable, null); - } - return false; - } - - return true; - } - - /** - * Tests if the field is pubic, static and one of int or int[]. - */ - private static boolean isValidRField(Field field) { - int modifiers = field.getModifiers(); - boolean isAcceptable = Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers); - Class<?> type = field.getType(); - return isAcceptable && type == int.class || - (type.isArray() && type.getComponentType() == int.class); - - } - - private static void parseStyleable() throws Exception { - // R.attr doesn't contain all the needed values. There are too many resources in the - // framework for all to be in the R class. Only the ones specified manually in - // res/values/symbols.xml are put in R class. Since, we need to create a map of all attr - // values, we try and find them from the styleables. - - // There were 1500 elements in this map at M timeframe. - Map<String, Integer> revRAttrMap = new HashMap<>(2048); - sRevRMap.put(ResourceType.ATTR, revRAttrMap); - // There were 2000 elements in this map at M timeframe. - Map<String, Integer> revRStyleableMap = new HashMap<>(3072); - sRevRMap.put(ResourceType.STYLEABLE, revRStyleableMap); - Class<?> c = com.android.internal.R.styleable.class; - Field[] fields = c.getDeclaredFields(); - // Sort the fields to bring all arrays to the beginning, so that indices into the array are - // able to refer back to the arrays (i.e. no forward references). - Arrays.sort(fields, (o1, o2) -> { - if (o1 == o2) { - return 0; - } - Class<?> t1 = o1.getType(); - Class<?> t2 = o2.getType(); - if (t1.isArray() && !t2.isArray()) { - return -1; - } else if (t2.isArray() && !t1.isArray()) { - return 1; - } - return o1.getName().compareTo(o2.getName()); - }); - Map<String, int[]> styleables = new HashMap<>(); - for (Field field : fields) { - if (!isValidRField(field)) { - // Only consider public static fields that are int or int[]. - // Don't check the final flag as it may have been modified by layoutlib_create. - continue; - } - String name = field.getName(); - if (field.getType().isArray()) { - int[] styleableValue = (int[]) field.get(null); - styleables.put(name, styleableValue); - continue; - } - // Not an array. - String arrayName = name; - int[] arrayValue = null; - int index; - while ((index = arrayName.lastIndexOf('_')) >= 0) { - // Find the name of the corresponding styleable. - // Search in reverse order so that attrs like LinearLayout_Layout_layout_gravity - // are mapped to LinearLayout_Layout and not to LinearLayout. - arrayName = arrayName.substring(0, index); - arrayValue = styleables.get(arrayName); - if (arrayValue != null) { - break; - } - } - index = (Integer) field.get(null); - if (arrayValue != null) { - String attrName = name.substring(arrayName.length() + 1); - int attrValue = arrayValue[index]; - //noinspection deprecation - sRMap.put(attrValue, Pair.of(ResourceType.ATTR, attrName)); - revRAttrMap.put(attrName, attrValue); - } - //noinspection deprecation - sRMap.put(index, Pair.of(ResourceType.STYLEABLE, name)); - revRStyleableMap.put(name, index); - } - } - - @Override - public boolean dispose() { - BridgeAssetManager.clearSystem(); - - // dispose of the default typeface. - Typeface_Delegate.resetDefaults(); - Typeface.sDynamicTypefaceCache.evictAll(); - - return true; - } - - /** - * Starts a layout session by inflating and rendering it. The method returns a - * {@link RenderSession} on which further actions can be taken. - * <p/> - * If {@link SessionParams} includes the {@link RenderParamsFlags#FLAG_DO_NOT_RENDER_ON_CREATE}, - * this method will only inflate the layout but will NOT render it. - * @param params the {@link SessionParams} object with all the information necessary to create - * the scene. - * @return a new {@link RenderSession} object that contains the result of the layout. - * @since 5 - */ - @Override - public RenderSession createSession(SessionParams params) { - try { - Result lastResult; - RenderSessionImpl scene = new RenderSessionImpl(params); - try { - prepareThread(); - lastResult = scene.init(params.getTimeout()); - if (lastResult.isSuccess()) { - lastResult = scene.inflate(); - - boolean doNotRenderOnCreate = Boolean.TRUE.equals( - params.getFlag(RenderParamsFlags.FLAG_DO_NOT_RENDER_ON_CREATE)); - if (lastResult.isSuccess() && !doNotRenderOnCreate) { - lastResult = scene.render(true /*freshRender*/); - } - } - } finally { - scene.release(); - cleanupThread(); - } - - return new BridgeRenderSession(scene, lastResult); - } catch (Throwable t) { - // get the real cause of the exception. - Throwable t2 = t; - while (t2.getCause() != null) { - t2 = t.getCause(); - } - return new BridgeRenderSession(null, - ERROR_UNKNOWN.createResult(t2.getMessage(), t)); - } - } - - @Override - public Result renderDrawable(DrawableParams params) { - try { - Result lastResult; - RenderDrawable action = new RenderDrawable(params); - try { - prepareThread(); - lastResult = action.init(params.getTimeout()); - if (lastResult.isSuccess()) { - lastResult = action.render(); - } - } finally { - action.release(); - cleanupThread(); - } - - return lastResult; - } catch (Throwable t) { - // get the real cause of the exception. - Throwable t2 = t; - while (t2.getCause() != null) { - t2 = t.getCause(); - } - return ERROR_UNKNOWN.createResult(t2.getMessage(), t); - } - } - - @Override - public void clearCaches(Object projectKey) { - if (projectKey != null) { - sProjectBitmapCache.remove(projectKey); - sProject9PatchCache.remove(projectKey); - } - } - - @Override - public Result getViewParent(Object viewObject) { - if (viewObject instanceof View) { - return Status.SUCCESS.createResult(((View)viewObject).getParent()); - } - - throw new IllegalArgumentException("viewObject is not a View"); - } - - @Override - public Result getViewIndex(Object viewObject) { - if (viewObject instanceof View) { - View view = (View) viewObject; - ViewParent parentView = view.getParent(); - - if (parentView instanceof ViewGroup) { - Status.SUCCESS.createResult(((ViewGroup) parentView).indexOfChild(view)); - } - - return Status.SUCCESS.createResult(); - } - - throw new IllegalArgumentException("viewObject is not a View"); - } - - @Override - public boolean isRtl(String locale) { - return isLocaleRtl(locale); - } - - public static boolean isLocaleRtl(String locale) { - if (locale == null) { - locale = ""; - } - ULocale uLocale = new ULocale(locale); - return uLocale.getCharacterOrientation().equals(ICU_LOCALE_DIRECTION_RTL); - } - - /** - * Returns the lock for the bridge - */ - public static ReentrantLock getLock() { - return sLock; - } - - /** - * Prepares the current thread for rendering. - * - * Note that while this can be called several time, the first call to {@link #cleanupThread()} - * will do the clean-up, and make the thread unable to do further scene actions. - */ - public synchronized static void prepareThread() { - // we need to make sure the Looper has been initialized for this thread. - // this is required for View that creates Handler objects. - if (Looper.myLooper() == null) { - Looper.prepareMainLooper(); - } - } - - /** - * Cleans up thread-specific data. After this, the thread cannot be used for scene actions. - * <p> - * Note that it doesn't matter how many times {@link #prepareThread()} was called, a single - * call to this will prevent the thread from doing further scene actions - */ - public synchronized static void cleanupThread() { - // clean up the looper - Looper_Accessor.cleanupThread(); - } - - public static LayoutLog getLog() { - return sCurrentLog; - } - - public static void setLog(LayoutLog log) { - // check only the thread currently owning the lock can do this. - if (!sLock.isHeldByCurrentThread()) { - throw new IllegalStateException("scene must be acquired first. see #acquire(long)"); - } - - if (log != null) { - sCurrentLog = log; - } else { - sCurrentLog = sDefaultLog; - } - } - - /** - * Returns details of a framework resource from its integer value. - * @param value the integer value - * @return a Pair containing the resource type and name, or null if the id - * does not match any resource. - */ - @SuppressWarnings("deprecation") - public static Pair<ResourceType, String> resolveResourceId(int value) { - Pair<ResourceType, String> pair = sRMap.get(value); - if (pair == null) { - pair = sDynamicIds.resolveId(value); - } - return pair; - } - - /** - * Returns the integer id of a framework resource, from a given resource type and resource name. - * <p/> - * If no resource is found, it creates a dynamic id for the resource. - * - * @param type the type of the resource - * @param name the name of the resource. - * - * @return an {@link Integer} containing the resource id. - */ - @NonNull - public static Integer getResourceId(ResourceType type, String name) { - Map<String, Integer> map = sRevRMap.get(type); - Integer value = null; - if (map != null) { - value = map.get(name); - } - - return value == null ? sDynamicIds.getId(type, name) : value; - - } - - /** - * Returns the list of possible enums for a given attribute name. - */ - public static Map<String, Integer> getEnumValues(String attributeName) { - if (sEnumValueMap != null) { - return sEnumValueMap.get(attributeName); - } - - return null; - } - - /** - * Returns the platform build properties. - */ - public static Map<String, String> getPlatformProperties() { - return sPlatformProperties; - } - - /** - * Returns the bitmap for a specific path, from a specific project cache, or from the - * framework cache. - * @param value the path of the bitmap - * @param projectKey the key of the project, or null to query the framework cache. - * @return the cached Bitmap or null if not found. - */ - public static Bitmap getCachedBitmap(String value, Object projectKey) { - if (projectKey != null) { - Map<String, SoftReference<Bitmap>> map = sProjectBitmapCache.get(projectKey); - if (map != null) { - SoftReference<Bitmap> ref = map.get(value); - if (ref != null) { - return ref.get(); - } - } - } else { - SoftReference<Bitmap> ref = sFrameworkBitmapCache.get(value); - if (ref != null) { - return ref.get(); - } - } - - return null; - } - - /** - * Sets a bitmap in a project cache or in the framework cache. - * @param value the path of the bitmap - * @param bmp the Bitmap object - * @param projectKey the key of the project, or null to put the bitmap in the framework cache. - */ - public static void setCachedBitmap(String value, Bitmap bmp, Object projectKey) { - if (projectKey != null) { - Map<String, SoftReference<Bitmap>> map = - sProjectBitmapCache.computeIfAbsent(projectKey, k -> new HashMap<>()); - - map.put(value, new SoftReference<>(bmp)); - } else { - sFrameworkBitmapCache.put(value, new SoftReference<>(bmp)); - } - } - - /** - * Returns the 9 patch chunk for a specific path, from a specific project cache, or from the - * framework cache. - * @param value the path of the 9 patch - * @param projectKey the key of the project, or null to query the framework cache. - * @return the cached 9 patch or null if not found. - */ - public static NinePatchChunk getCached9Patch(String value, Object projectKey) { - if (projectKey != null) { - Map<String, SoftReference<NinePatchChunk>> map = sProject9PatchCache.get(projectKey); - - if (map != null) { - SoftReference<NinePatchChunk> ref = map.get(value); - if (ref != null) { - return ref.get(); - } - } - } else { - SoftReference<NinePatchChunk> ref = sFramework9PatchCache.get(value); - if (ref != null) { - return ref.get(); - } - } - - return null; - } - - /** - * Sets a 9 patch chunk in a project cache or in the framework cache. - * @param value the path of the 9 patch - * @param ninePatch the 9 patch object - * @param projectKey the key of the project, or null to put the bitmap in the framework cache. - */ - public static void setCached9Patch(String value, NinePatchChunk ninePatch, Object projectKey) { - if (projectKey != null) { - Map<String, SoftReference<NinePatchChunk>> map = - sProject9PatchCache.computeIfAbsent(projectKey, k -> new HashMap<>()); - - map.put(value, new SoftReference<>(ninePatch)); - } else { - sFramework9PatchCache.put(value, new SoftReference<>(ninePatch)); - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java deleted file mode 100644 index 62287669577c..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge; - -/** - * Constant definition class.<br> - * <br> - * Most constants have a prefix defining the content. - * <ul> - * <li><code>WS_</code> Workspace path constant. Those are absolute paths, - * from the project root.</li> - * <li><code>OS_</code> OS path constant. These paths are different depending on the platform.</li> - * <li><code>FN_</code> File name constant.</li> - * <li><code>FD_</code> Folder name constant.</li> - * <li><code>EXT_</code> File extension constant. This does NOT include a dot.</li> - * <li><code>DOT_</code> File extension constant. This start with a dot.</li> - * <li><code>RE_</code> Regexp constant.</li> - * <li><code>NS_</code> Namespace constant.</li> - * <li><code>CLASS_</code> Fully qualified class name.</li> - * </ul> - * - */ -public class BridgeConstants { - - /** Namespace for the resource XML */ - public final static String NS_RESOURCES = "http://schemas.android.com/apk/res/android"; - - /** App auto namespace */ - public final static String NS_APP_RES_AUTO = "http://schemas.android.com/apk/res-auto"; - public final static String NS_TOOLS_URI = "http://schemas.android.com/tools"; - - public final static String R = "com.android.internal.R"; - - - public final static String MATCH_PARENT = "match_parent"; - public final static String FILL_PARENT = "fill_parent"; - public final static String WRAP_CONTENT = "wrap_content"; - - // Should be kept in sync with LayoutMetadata.KEY_LV_ITEM in tools/adt/idea - /** Attribute in the tools namespace used to specify layout manager for RecyclerView. */ - @SuppressWarnings("SpellCheckingInspection") - public static final String ATTR_LIST_ITEM = "listitem"; - public static final String ATTR_OPEN_DRAWER = "openDrawer"; -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java deleted file mode 100644 index fdf6d63b1cb2..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge; - -import com.android.ide.common.rendering.api.IAnimationListener; -import com.android.ide.common.rendering.api.ILayoutPullParser; -import com.android.ide.common.rendering.api.RenderParams; -import com.android.ide.common.rendering.api.RenderSession; -import com.android.ide.common.rendering.api.Result; -import com.android.ide.common.rendering.api.ViewInfo; -import com.android.layoutlib.bridge.impl.RenderSessionImpl; -import com.android.tools.layoutlib.java.System_Delegate; -import com.android.util.PropertiesMap; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.view.View; -import android.view.ViewGroup; - -import java.awt.image.BufferedImage; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -/** - * An implementation of {@link RenderSession}. - * - * This is a pretty basic class that does almost nothing. All of the work is done in - * {@link RenderSessionImpl}. - * - */ -public class BridgeRenderSession extends RenderSession { - - @Nullable - private final RenderSessionImpl mSession; - @NonNull - private Result mLastResult; - - @Override - public Result getResult() { - return mLastResult; - } - - @Override - public BufferedImage getImage() { - return mSession != null ? mSession.getImage() : - new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB); - } - - @Override - public boolean isAlphaChannelImage() { - return mSession != null && mSession.isAlphaChannelImage(); - } - - @Override - public List<ViewInfo> getRootViews() { - return mSession != null ? mSession.getViewInfos() : Collections.emptyList(); - } - - @Override - public List<ViewInfo> getSystemRootViews() { - return mSession != null ? mSession.getSystemViewInfos() : Collections.emptyList(); - } - - @Override - public Map<Object, PropertiesMap> getDefaultProperties() { - return mSession != null ? mSession.getDefaultProperties() : Collections.emptyMap(); - } - - @Override - public Result measure(long timeout) { - if (mSession != null) { - try { - Bridge.prepareThread(); - mLastResult = mSession.acquire(timeout); - if (mLastResult.isSuccess()) { - mSession.invalidateRenderingSize(); - mLastResult = mSession.measure(); - } - } finally { - mSession.release(); - Bridge.cleanupThread(); - } - } - - return mLastResult; - } - - @Override - public Result render(long timeout, boolean forceMeasure) { - if (mSession != null) { - try { - Bridge.prepareThread(); - mLastResult = mSession.acquire(timeout); - if (mLastResult.isSuccess()) { - if (forceMeasure) { - mSession.invalidateRenderingSize(); - } - mLastResult = mSession.render(false /*freshRender*/); - } - } finally { - mSession.release(); - Bridge.cleanupThread(); - } - } - - return mLastResult; - } - - @Override - public Result animate(Object targetObject, String animationName, - boolean isFrameworkAnimation, IAnimationListener listener) { - if (mSession != null) { - try { - Bridge.prepareThread(); - mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT); - if (mLastResult.isSuccess()) { - mLastResult = mSession.animate(targetObject, animationName, isFrameworkAnimation, - listener); - } - } finally { - mSession.release(); - Bridge.cleanupThread(); - } - } - - return mLastResult; - } - - @Override - public Result insertChild(Object parentView, ILayoutPullParser childXml, int index, - IAnimationListener listener) { - if (!(parentView instanceof ViewGroup)) { - throw new IllegalArgumentException("parentView is not a ViewGroup"); - } - - if (mSession != null) { - try { - Bridge.prepareThread(); - mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT); - if (mLastResult.isSuccess()) { - mLastResult = - mSession.insertChild((ViewGroup) parentView, childXml, index, listener); - } - } finally { - mSession.release(); - Bridge.cleanupThread(); - } - } - - return mLastResult; - } - - - @Override - public Result moveChild(Object parentView, Object childView, int index, - Map<String, String> layoutParams, IAnimationListener listener) { - if (!(parentView instanceof ViewGroup)) { - throw new IllegalArgumentException("parentView is not a ViewGroup"); - } - if (!(childView instanceof View)) { - throw new IllegalArgumentException("childView is not a View"); - } - - if (mSession != null) { - try { - Bridge.prepareThread(); - mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT); - if (mLastResult.isSuccess()) { - mLastResult = mSession.moveChild((ViewGroup) parentView, (View) childView, index, - layoutParams, listener); - } - } finally { - mSession.release(); - Bridge.cleanupThread(); - } - } - - return mLastResult; - } - - @Override - public Result removeChild(Object childView, IAnimationListener listener) { - if (!(childView instanceof View)) { - throw new IllegalArgumentException("childView is not a View"); - } - - if (mSession != null) { - try { - Bridge.prepareThread(); - mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT); - if (mLastResult.isSuccess()) { - mLastResult = mSession.removeChild((View) childView, listener); - } - } finally { - mSession.release(); - Bridge.cleanupThread(); - } - } - - return mLastResult; - } - - @Override - public void setSystemTimeNanos(long nanos) { - System_Delegate.setNanosTime(nanos); - } - - @Override - public void setSystemBootTimeNanos(long nanos) { - System_Delegate.setBootTimeNanos(nanos); - } - - @Override - public void setElapsedFrameTimeNanos(long nanos) { - if (mSession != null) { - mSession.setElapsedFrameTimeNanos(nanos); - } - } - - @Override - public void dispose() { - if (mSession != null) { - mSession.dispose(); - } - } - - /*package*/ BridgeRenderSession(@Nullable RenderSessionImpl scene, @NonNull Result lastResult) { - mSession = scene; - if (scene != null) { - mSession.setScene(this); - } - mLastResult = lastResult; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java deleted file mode 100644 index e10f20dfbbca..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.Gravity; -import android.view.View; -import android.view.ViewGroup; -import android.widget.FrameLayout; -import android.widget.TextView; - -/** - * Base class for mocked views. - * <p/> - * FrameLayout with a single TextView. Doesn't allow adding any other views to itself. - */ -public class MockView extends FrameLayout { - - private final TextView mView; - - public MockView(Context context) { - this(context, null); - } - - public MockView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public MockView(Context context, AttributeSet attrs, int defStyleAttr) { - this(context, attrs, defStyleAttr, 0); - } - - public MockView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - mView = new TextView(context, attrs); - mView.setTextColor(0xFF000000); - setGravity(Gravity.CENTER); - setText(getClass().getSimpleName()); - addView(mView); - setBackgroundColor(0xFF7F7F7F); - } - - // Only allow adding one TextView. - @Override - public void addView(View child) { - if (child == mView) { - super.addView(child); - } - } - - @Override - public void addView(View child, int index) { - if (child == mView) { - super.addView(child, index); - } - } - - @Override - public void addView(View child, int width, int height) { - if (child == mView) { - super.addView(child, width, height); - } - } - - @Override - public void addView(View child, ViewGroup.LayoutParams params) { - if (child == mView) { - super.addView(child, params); - } - } - - @Override - public void addView(View child, int index, ViewGroup.LayoutParams params) { - if (child == mView) { - super.addView(child, index, params); - } - } - - // The following methods are called by the IDE via reflection, and should be considered part - // of the API. - // Historically, MockView used to be a textView and had these methods. Now, we simply delegate - // them to the contained textView. - - public void setText(CharSequence text) { - mView.setText(text); - } - - @SuppressWarnings("WeakerAccess") // This method is used from Studio - public void setGravity(int gravity) { - mView.setGravity(gravity); - } -} 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 deleted file mode 100644 index faaf1056bc9d..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/AndroidLocale.java +++ /dev/null @@ -1,72 +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 com.android.layoutlib.bridge.android; - -import com.android.layoutlib.bridge.impl.RenderAction; - -import android.icu.util.ULocale; - -import java.util.Locale; - -/** - * This class provides an alternate implementation for {@code java.util.Locale#toLanguageTag} - * which is only available after Java 6. - * - * The create tool re-writes references to the above mentioned method to this one. Hence it's - * imperative that this class is not deleted unless the create tool is modified. - */ -@SuppressWarnings("UnusedDeclaration") -public class AndroidLocale { - - public static String toLanguageTag(Locale locale) { - return ULocale.forLocale(locale).toLanguageTag(); - } - - public static String adjustLanguageCode(String languageCode) { - String adjusted = languageCode.toLowerCase(Locale.US); - // Map new language codes to the obsolete language - // codes so the correct resource bundles will be used. - if (languageCode.equals("he")) { - adjusted = "iw"; - } else if (languageCode.equals("id")) { - adjusted = "in"; - } else if (languageCode.equals("yi")) { - adjusted = "ji"; - } - - return adjusted; - } - - public static Locale forLanguageTag(String tag) { - return ULocale.forLanguageTag(tag).toLocale(); - } - - public static String getScript(Locale locale) { - return ULocale.forLocale(locale).getScript(); - } - - public static Locale getDefault() { - BridgeContext context = RenderAction.getCurrentContext(); - if (context != null) { - Locale locale = context.getConfiguration().locale; - if (locale != null) { - return locale; - } - } - return Locale.getDefault(); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java deleted file mode 100644 index c827f178279e..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.android; - -import android.content.ContentProviderOperation; -import android.content.ContentProviderResult; -import android.content.ContentValues; -import android.content.IContentProvider; -import android.content.OperationApplicationException; -import android.content.res.AssetFileDescriptor; -import android.database.Cursor; -import android.net.Uri; -import android.os.Bundle; -import android.os.IBinder; -import android.os.ICancellationSignal; -import android.os.ParcelFileDescriptor; -import android.os.RemoteException; - -import java.io.FileNotFoundException; -import java.util.ArrayList; - -/** - * Mock implementation of {@link IContentProvider}. - * - * TODO: never return null when the method is not supposed to. Return fake data instead. - */ -public final class BridgeContentProvider implements IContentProvider { - @Override - public ContentProviderResult[] applyBatch(String callingPackage, - ArrayList<ContentProviderOperation> arg0) - throws RemoteException, OperationApplicationException { - // TODO Auto-generated method stub - return null; - } - - @Override - public int bulkInsert(String callingPackage, Uri arg0, ContentValues[] arg1) - throws RemoteException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public Bundle call(String callingPackage, String arg0, String arg1, Bundle arg2) - throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public int delete(String callingPackage, Uri arg0, String arg1, String[] arg2) - throws RemoteException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public String getType(Uri arg0) throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Uri insert(String callingPackage, Uri arg0, ContentValues arg1) throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public AssetFileDescriptor openAssetFile( - String callingPackage, Uri arg0, String arg1, ICancellationSignal signal) - throws RemoteException, FileNotFoundException { - // TODO Auto-generated method stub - return null; - } - - @Override - public ParcelFileDescriptor openFile( - String callingPackage, Uri arg0, String arg1, ICancellationSignal signal, IBinder token) - throws RemoteException, FileNotFoundException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Cursor query(String callingPackage, Uri arg0, String[] arg1, - Bundle arg3, ICancellationSignal arg4) throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public int update(String callingPackage, Uri arg0, ContentValues arg1, String arg2, - String[] arg3) throws RemoteException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public IBinder asBinder() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String[] getStreamTypes(Uri arg0, String arg1) throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public AssetFileDescriptor openTypedAssetFile(String callingPackage, Uri arg0, String arg1, - Bundle arg2, ICancellationSignal signal) throws RemoteException, FileNotFoundException { - // TODO Auto-generated method stub - return null; - } - - @Override - public ICancellationSignal createCancellationSignal() throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - - @Override - public Uri canonicalize(String callingPkg, Uri uri) throws RemoteException { - return null; - } - - @Override - public Uri uncanonicalize(String callingPkg, Uri uri) throws RemoteException { - return null; - } - - @Override - public boolean refresh(String callingPkg, Uri url, Bundle args, - ICancellationSignal cancellationSignal) throws RemoteException { - return false; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentResolver.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentResolver.java deleted file mode 100644 index 8d259d70121e..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentResolver.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.android; - -import android.content.ContentResolver; -import android.content.Context; -import android.content.IContentProvider; -import android.database.ContentObserver; -import android.net.Uri; -import android.os.Bundle; - -/** - * A mock content resolver for the LayoutLib Bridge. - * <p/> - * It won't serve any actual data but it's good enough for all - * the widgets which expect to have a content resolver available via - * {@link BridgeContext#getContentResolver()}. - */ -public class BridgeContentResolver extends ContentResolver { - - private BridgeContentProvider mProvider = null; - - public BridgeContentResolver(Context context) { - super(context); - } - - @Override - public IContentProvider acquireProvider(Context c, String name) { - if (mProvider == null) { - mProvider = new BridgeContentProvider(); - } - - return mProvider; - } - - @Override - public IContentProvider acquireExistingProvider(Context c, String name) { - if (mProvider == null) { - mProvider = new BridgeContentProvider(); - } - - return mProvider; - } - - @Override - public boolean releaseProvider(IContentProvider icp) { - // ignore - return false; - } - - @Override - protected IContentProvider acquireUnstableProvider(Context c, String name) { - return acquireProvider(c, name); - } - - @Override - public boolean releaseUnstableProvider(IContentProvider icp) { - return releaseProvider(icp); - } - - /** @hide */ - @Override - public void unstableProviderDied(IContentProvider icp) { - } - - /** - * Stub for the layoutlib bridge content resolver. - */ - @Override - public void registerContentObserver(Uri uri, boolean notifyForDescendents, - ContentObserver observer) { - // pass - } - - /** - * Stub for the layoutlib bridge content resolver. - */ - @Override - public void unregisterContentObserver(ContentObserver observer) { - // pass - } - - /** - * Stub for the layoutlib bridge content resolver. - */ - @Override - public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) { - // pass - } - - /** - * Stub for the layoutlib bridge content resolver. - */ - @Override - public void startSync(Uri uri, Bundle extras) { - // pass - } - - /** - * Stub for the layoutlib bridge content resolver. - */ - @Override - public void cancelSync(Uri uri) { - // pass - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java deleted file mode 100644 index 8bd924ea9cfb..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java +++ /dev/null @@ -1,2059 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.android; - -import com.android.SdkConstants; -import com.android.ide.common.rendering.api.AssetRepository; -import com.android.ide.common.rendering.api.ILayoutPullParser; -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.ide.common.rendering.api.LayoutlibCallback; -import com.android.ide.common.rendering.api.RenderResources; -import com.android.ide.common.rendering.api.ResourceReference; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.rendering.api.StyleResourceValue; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.BridgeConstants; -import com.android.layoutlib.bridge.android.view.WindowManagerImpl; -import com.android.layoutlib.bridge.impl.ParserFactory; -import com.android.layoutlib.bridge.impl.Stack; -import com.android.resources.ResourceType; -import com.android.util.Pair; -import com.android.util.PropertiesMap; -import com.android.util.PropertiesMap.Property; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.app.Notification; -import android.app.SystemServiceRegistry_Accessor; -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.ContentResolver; -import android.content.Context; -import android.content.ContextWrapper; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.IntentSender; -import android.content.ServiceConnection; -import android.content.SharedPreferences; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.res.AssetManager; -import android.content.res.BridgeAssetManager; -import android.content.res.BridgeTypedArray; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.content.res.Resources.Theme; -import android.content.res.Resources_Delegate; -import android.database.DatabaseErrorHandler; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteDatabase.CursorFactory; -import android.graphics.Bitmap; -import android.graphics.Color; -import android.graphics.drawable.Drawable; -import android.hardware.display.DisplayManager; -import android.net.Uri; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.os.IInterface; -import android.os.Looper; -import android.os.Parcel; -import android.os.PowerManager; -import android.os.RemoteException; -import android.os.ResultReceiver; -import android.os.ShellCallback; -import android.os.UserHandle; -import android.util.AttributeSet; -import android.util.DisplayMetrics; -import android.util.TypedValue; -import android.view.BridgeInflater; -import android.view.Display; -import android.view.DisplayAdjustments; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.WindowManager; -import android.view.accessibility.AccessibilityManager; -import android.view.textservice.TextServicesManager; - -import java.io.File; -import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; - -import static android.os._Original_Build.VERSION_CODES.JELLY_BEAN_MR1; -import static com.android.layoutlib.bridge.android.RenderParamsFlags.FLAG_KEY_APPLICATION_PACKAGE; - -/** - * Custom implementation of Context/Activity to handle non compiled resources. - */ -@SuppressWarnings("deprecation") // For use of Pair. -public class BridgeContext extends Context { - private static final String PREFIX_THEME_APPCOMPAT = "Theme.AppCompat"; - - private static final Map<String, ResourceValue> FRAMEWORK_PATCHED_VALUES = new HashMap<>(2); - private static final Map<String, ResourceValue> FRAMEWORK_REPLACE_VALUES = new HashMap<>(3); - - static { - FRAMEWORK_PATCHED_VALUES.put("animateFirstView", new ResourceValue( - ResourceType.BOOL, "animateFirstView", "false", false)); - FRAMEWORK_PATCHED_VALUES.put("animateLayoutChanges", - new ResourceValue(ResourceType.BOOL, "animateLayoutChanges", "false", false)); - - - FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionItemLayout", - new ResourceValue(ResourceType.LAYOUT, "textEditSuggestionItemLayout", - "text_edit_suggestion_item", true)); - FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionContainerLayout", - new ResourceValue(ResourceType.LAYOUT, "textEditSuggestionContainerLayout", - "text_edit_suggestion_container", true)); - FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionHighlightStyle", - new ResourceValue(ResourceType.STYLE, "textEditSuggestionHighlightStyle", - "TextAppearance.Holo.SuggestionHighlight", true)); - - } - - /** The map adds cookies to each view so that IDE can link xml tags to views. */ - private final HashMap<View, Object> mViewKeyMap = new HashMap<>(); - /** - * In some cases, when inflating an xml, some objects are created. Then later, the objects are - * converted to views. This map stores the mapping from objects to cookies which can then be - * used to populate the mViewKeyMap. - */ - private final HashMap<Object, Object> mViewKeyHelpMap = new HashMap<>(); - private final BridgeAssetManager mAssets; - private Resources mSystemResources; - private final Object mProjectKey; - private final DisplayMetrics mMetrics; - private final RenderResources mRenderResources; - private final Configuration mConfig; - private final ApplicationInfo mApplicationInfo; - private final LayoutlibCallback mLayoutlibCallback; - private final WindowManager mWindowManager; - private final DisplayManager mDisplayManager; - private final HashMap<View, Integer> mScrollYPos = new HashMap<>(); - private final HashMap<View, Integer> mScrollXPos = new HashMap<>(); - - private Resources.Theme mTheme; - - private final Map<Object, PropertiesMap> mDefaultPropMaps = new IdentityHashMap<>(); - - // maps for dynamically generated id representing style objects (StyleResourceValue) - @Nullable - private Map<Integer, StyleResourceValue> mDynamicIdToStyleMap; - private Map<StyleResourceValue, Integer> mStyleToDynamicIdMap; - private int mDynamicIdGenerator = 0x02030000; // Base id for R.style in custom namespace - - // cache for TypedArray generated from StyleResourceValue object - private TypedArrayCache mTypedArrayCache; - private BridgeInflater mBridgeInflater; - - private BridgeContentResolver mContentResolver; - - private final Stack<BridgeXmlBlockParser> mParserStack = new Stack<>(); - private SharedPreferences mSharedPreferences; - private ClassLoader mClassLoader; - private IBinder mBinder; - private PackageManager mPackageManager; - private Boolean mIsThemeAppCompat; - - /** - * Some applications that target both pre API 17 and post API 17, set the newer attrs to - * reference the older ones. For example, android:paddingStart will resolve to - * android:paddingLeft. This way the apps need to only define paddingLeft at any other place. - * This a map from value to attribute name. Warning for missing references shouldn't be logged - * if value and attr name pair is the same as an entry in this map. - */ - private static Map<String, String> RTL_ATTRS = new HashMap<>(10); - - static { - RTL_ATTRS.put("?android:attr/paddingLeft", "paddingStart"); - RTL_ATTRS.put("?android:attr/paddingRight", "paddingEnd"); - RTL_ATTRS.put("?android:attr/layout_marginLeft", "layout_marginStart"); - RTL_ATTRS.put("?android:attr/layout_marginRight", "layout_marginEnd"); - RTL_ATTRS.put("?android:attr/layout_toLeftOf", "layout_toStartOf"); - RTL_ATTRS.put("?android:attr/layout_toRightOf", "layout_toEndOf"); - RTL_ATTRS.put("?android:attr/layout_alignParentLeft", "layout_alignParentStart"); - RTL_ATTRS.put("?android:attr/layout_alignParentRight", "layout_alignParentEnd"); - RTL_ATTRS.put("?android:attr/drawableLeft", "drawableStart"); - RTL_ATTRS.put("?android:attr/drawableRight", "drawableEnd"); - } - - /** - * @param projectKey An Object identifying the project. This is used for the cache mechanism. - * @param metrics the {@link DisplayMetrics}. - * @param renderResources the configured resources (both framework and projects) for this - * render. - * @param config the Configuration object for this render. - * @param targetSdkVersion the targetSdkVersion of the application. - */ - public BridgeContext(Object projectKey, DisplayMetrics metrics, - RenderResources renderResources, - AssetRepository assets, - LayoutlibCallback layoutlibCallback, - Configuration config, - int targetSdkVersion, - boolean hasRtlSupport) { - mProjectKey = projectKey; - mMetrics = metrics; - mLayoutlibCallback = layoutlibCallback; - - mRenderResources = renderResources; - mConfig = config; - AssetManager systemAssetManager = AssetManager.getSystem(); - if (systemAssetManager instanceof BridgeAssetManager) { - mAssets = (BridgeAssetManager) systemAssetManager; - } else { - throw new AssertionError("Creating BridgeContext without initializing Bridge"); - } - mAssets.setAssetRepository(assets); - - mApplicationInfo = new ApplicationInfo(); - mApplicationInfo.targetSdkVersion = targetSdkVersion; - if (hasRtlSupport) { - mApplicationInfo.flags = mApplicationInfo.flags | ApplicationInfo.FLAG_SUPPORTS_RTL; - } - - mWindowManager = new WindowManagerImpl(mMetrics); - mDisplayManager = new DisplayManager(this); - } - - /** - * Initializes the {@link Resources} singleton to be linked to this {@link Context}, its - * {@link DisplayMetrics}, {@link Configuration}, and {@link LayoutlibCallback}. - * - * @see #disposeResources() - */ - public void initResources() { - AssetManager assetManager = AssetManager.getSystem(); - - mSystemResources = Resources_Delegate.initSystem( - this, - assetManager, - mMetrics, - mConfig, - mLayoutlibCallback); - mTheme = mSystemResources.newTheme(); - } - - /** - * Disposes the {@link Resources} singleton. - */ - public void disposeResources() { - Resources_Delegate.disposeSystem(); - } - - public void setBridgeInflater(BridgeInflater inflater) { - mBridgeInflater = inflater; - } - - public void addViewKey(View view, Object viewKey) { - mViewKeyMap.put(view, viewKey); - } - - public Object getViewKey(View view) { - return mViewKeyMap.get(view); - } - - public void addCookie(Object o, Object cookie) { - mViewKeyHelpMap.put(o, cookie); - } - - public Object getCookie(Object o) { - return mViewKeyHelpMap.get(o); - } - - public Object getProjectKey() { - return mProjectKey; - } - - public DisplayMetrics getMetrics() { - return mMetrics; - } - - public LayoutlibCallback getLayoutlibCallback() { - return mLayoutlibCallback; - } - - public RenderResources getRenderResources() { - return mRenderResources; - } - - public Map<Object, PropertiesMap> getDefaultProperties() { - return mDefaultPropMaps; - } - - public Configuration getConfiguration() { - return mConfig; - } - - /** - * Adds a parser to the stack. - * @param parser the parser to add. - */ - public void pushParser(BridgeXmlBlockParser parser) { - if (ParserFactory.LOG_PARSER) { - System.out.println("PUSH " + parser.getParser().toString()); - } - mParserStack.push(parser); - } - - /** - * Removes the parser at the top of the stack - */ - public void popParser() { - BridgeXmlBlockParser parser = mParserStack.pop(); - if (ParserFactory.LOG_PARSER) { - System.out.println("POPD " + parser.getParser().toString()); - } - } - - /** - * Returns the current parser at the top the of the stack. - * @return a parser or null. - */ - private BridgeXmlBlockParser getCurrentParser() { - return mParserStack.peek(); - } - - /** - * Returns the previous parser. - * @return a parser or null if there isn't any previous parser - */ - public BridgeXmlBlockParser getPreviousParser() { - if (mParserStack.size() < 2) { - return null; - } - return mParserStack.get(mParserStack.size() - 2); - } - - public boolean resolveThemeAttribute(int resId, TypedValue outValue, boolean resolveRefs) { - Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(resId); - boolean isFrameworkRes = true; - if (resourceInfo == null) { - resourceInfo = mLayoutlibCallback.resolveResourceId(resId); - isFrameworkRes = false; - } - - if (resourceInfo == null) { - return false; - } - - ResourceValue value = mRenderResources.findItemInTheme(resourceInfo.getSecond(), - isFrameworkRes); - if (resolveRefs) { - value = mRenderResources.resolveResValue(value); - } - - if (value == null) { - // unable to find the attribute. - return false; - } - - // check if this is a style resource - if (value instanceof StyleResourceValue) { - // get the id that will represent this style. - outValue.resourceId = getDynamicIdByStyle((StyleResourceValue) value); - return true; - } - - String stringValue = value.getValue(); - if (!stringValue.isEmpty()) { - if (stringValue.charAt(0) == '#') { - outValue.type = TypedValue.TYPE_INT_COLOR_ARGB8; - outValue.data = Color.parseColor(value.getValue()); - } - else if (stringValue.charAt(0) == '@') { - outValue.type = TypedValue.TYPE_REFERENCE; - } - - } - - int a; - // if this is a framework value. - if (value.isFramework()) { - // look for idName in the android R classes. - // use 0 a default res value as it's not a valid id value. - a = getFrameworkResourceValue(value.getResourceType(), value.getName(), 0 /*defValue*/); - } else { - // look for idName in the project R class. - // use 0 a default res value as it's not a valid id value. - a = getProjectResourceValue(value.getResourceType(), value.getName(), 0 /*defValue*/); - } - - if (a != 0) { - outValue.resourceId = a; - return true; - } - - // If the value is not a valid reference, fallback to pass the value as a string. - outValue.string = stringValue; - return true; - } - - - public ResourceReference resolveId(int id) { - // first get the String related to this id in the framework - Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(id); - - if (resourceInfo != null) { - return new ResourceReference(resourceInfo.getSecond(), true); - } - - // didn't find a match in the framework? look in the project. - if (mLayoutlibCallback != null) { - resourceInfo = mLayoutlibCallback.resolveResourceId(id); - - if (resourceInfo != null) { - return new ResourceReference(resourceInfo.getSecond(), false); - } - } - - // The base value for R.style is 0x01030000 and the custom style is 0x02030000. - // So, if the second byte is 03, it's probably a style. - if ((id >> 16 & 0xFF) == 0x03) { - return getStyleByDynamicId(id); - } - return null; - } - - public Pair<View, Boolean> inflateView(ResourceReference resource, ViewGroup parent, - @SuppressWarnings("SameParameterValue") boolean attachToRoot, - boolean skipCallbackParser) { - boolean isPlatformLayout = resource.isFramework(); - - if (!isPlatformLayout && !skipCallbackParser) { - // check if the project callback can provide us with a custom parser. - ILayoutPullParser parser = getParser(resource); - - if (parser != null) { - BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(parser, - this, resource.isFramework()); - try { - pushParser(blockParser); - return Pair.of( - mBridgeInflater.inflate(blockParser, parent, attachToRoot), - Boolean.TRUE); - } finally { - popParser(); - } - } - } - - ResourceValue resValue; - if (resource instanceof ResourceValue) { - resValue = (ResourceValue) resource; - } else { - if (isPlatformLayout) { - resValue = mRenderResources.getFrameworkResource(ResourceType.LAYOUT, - resource.getName()); - } else { - resValue = mRenderResources.getProjectResource(ResourceType.LAYOUT, - resource.getName()); - } - } - - if (resValue != null) { - - File xml = new File(resValue.getValue()); - if (xml.isFile()) { - // we need to create a pull parser around the layout XML file, and then - // give that to our XmlBlockParser - try { - XmlPullParser parser = ParserFactory.create(xml, true); - - // set the resource ref to have correct view cookies - mBridgeInflater.setResourceReference(resource); - - BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(parser, - this, resource.isFramework()); - try { - pushParser(blockParser); - return Pair.of( - mBridgeInflater.inflate(blockParser, parent, attachToRoot), - Boolean.FALSE); - } finally { - popParser(); - } - } catch (XmlPullParserException e) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "Failed to configure parser for " + xml, e, null /*data*/); - // we'll return null below. - } catch (FileNotFoundException e) { - // this shouldn't happen since we check above. - } finally { - mBridgeInflater.setResourceReference(null); - } - } else { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - String.format("File %s is missing!", xml), null); - } - } else { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - String.format("Layout %s%s does not exist.", isPlatformLayout ? "android:" : "", - resource.getName()), null); - } - - return Pair.of(null, Boolean.FALSE); - } - - /** - * Returns whether the current selected theme is based on AppCompat - */ - public boolean isAppCompatTheme() { - // If a cached value exists, return it. - if (mIsThemeAppCompat != null) { - return mIsThemeAppCompat; - } - // Ideally, we should check if the corresponding activity extends - // android.support.v7.app.ActionBarActivity, and not care about the theme name at all. - StyleResourceValue defaultTheme = mRenderResources.getDefaultTheme(); - // We can't simply check for parent using resources.themeIsParentOf() since the - // inheritance structure isn't really what one would expect. The first common parent - // between Theme.AppCompat.Light and Theme.AppCompat is Theme.Material (for v21). - boolean isThemeAppCompat = false; - for (int i = 0; i < 50; i++) { - if (defaultTheme == null) { - break; - } - // for loop ensures that we don't run into cyclic theme inheritance. - if (defaultTheme.getName().startsWith(PREFIX_THEME_APPCOMPAT)) { - isThemeAppCompat = true; - break; - } - defaultTheme = mRenderResources.getParent(defaultTheme); - } - mIsThemeAppCompat = isThemeAppCompat; - return isThemeAppCompat; - } - - @SuppressWarnings("deprecation") - private ILayoutPullParser getParser(ResourceReference resource) { - ILayoutPullParser parser; - if (resource instanceof ResourceValue) { - parser = mLayoutlibCallback.getParser((ResourceValue) resource); - } else { - parser = mLayoutlibCallback.getParser(resource.getName()); - } - return parser; - } - - // ------------ Context methods - - @Override - public Resources getResources() { - return mSystemResources; - } - - @Override - public Theme getTheme() { - return mTheme; - } - - @Override - public ClassLoader getClassLoader() { - // The documentation for this method states that it should return a class loader one can - // use to retrieve classes in this package. However, when called by LayoutInflater, we do - // not want the class loader to return app's custom views. - // This is so that the IDE can instantiate the custom views and also generate proper error - // messages in case of failure. This also enables the IDE to fallback to MockView in case - // there's an exception thrown when trying to inflate the custom view. - // To work around this issue, LayoutInflater is modified via LayoutLib Create tool to - // replace invocations of this method to a new method: getFrameworkClassLoader(). Also, - // the method is injected into Context. The implementation of getFrameworkClassLoader() is: - // "return getClass().getClassLoader();". This means that when LayoutInflater asks for - // the context ClassLoader, it gets only LayoutLib's ClassLoader which doesn't have - // access to the apps's custom views. - // This method can now return the right ClassLoader, which CustomViews can use to do the - // right thing. - if (mClassLoader == null) { - mClassLoader = new ClassLoader(getClass().getClassLoader()) { - @Override - protected Class<?> findClass(String name) throws ClassNotFoundException { - for (String prefix : BridgeInflater.getClassPrefixList()) { - if (name.startsWith(prefix)) { - // These are framework classes and should not be loaded from the app. - throw new ClassNotFoundException(name + " not found"); - } - } - return BridgeContext.this.mLayoutlibCallback.findClass(name); - } - }; - } - return mClassLoader; - } - - @Override - public Object getSystemService(String service) { - if (LAYOUT_INFLATER_SERVICE.equals(service)) { - return mBridgeInflater; - } - - if (TEXT_SERVICES_MANAGER_SERVICE.equals(service)) { - // we need to return a valid service to avoid NPE - return TextServicesManager.getInstance(); - } - - if (WINDOW_SERVICE.equals(service)) { - return mWindowManager; - } - - // needed by SearchView - if (INPUT_METHOD_SERVICE.equals(service)) { - return null; - } - - if (POWER_SERVICE.equals(service)) { - return new PowerManager(this, new BridgePowerManager(), new Handler()); - } - - if (DISPLAY_SERVICE.equals(service)) { - return mDisplayManager; - } - - if (ACCESSIBILITY_SERVICE.equals(service)) { - return AccessibilityManager.getInstance(this); - } - - if (AUTOFILL_MANAGER_SERVICE.equals(service)) { - return null; - } - - if (AUDIO_SERVICE.equals(service)) { - return null; - } - - assert false : "Unsupported Service: " + service; - return null; - } - - @Override - public String getSystemServiceName(Class<?> serviceClass) { - return SystemServiceRegistry_Accessor.getSystemServiceName(serviceClass); - } - - @Override - public final BridgeTypedArray obtainStyledAttributes(int[] attrs) { - return obtainStyledAttributes(0, attrs); - } - - @Override - public final BridgeTypedArray obtainStyledAttributes(int resId, int[] attrs) - throws Resources.NotFoundException { - StyleResourceValue style = null; - // get the StyleResourceValue based on the resId; - if (resId != 0) { - style = getStyleByDynamicId(resId); - - if (style == null) { - // In some cases, style may not be a dynamic id, so we do a full search. - ResourceReference ref = resolveId(resId); - if (ref != null) { - style = mRenderResources.getStyle(ref.getName(), ref.isFramework()); - } - } - - if (style == null) { - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE, - "Failed to find style with " + resId, null); - return null; - } - } - - if (mTypedArrayCache == null) { - mTypedArrayCache = new TypedArrayCache(); - } - - List<StyleResourceValue> currentThemes = mRenderResources.getAllThemes(); - - Pair<BridgeTypedArray, PropertiesMap> typeArrayAndPropertiesPair = - mTypedArrayCache.get(attrs, currentThemes, resId); - - if (typeArrayAndPropertiesPair == null) { - typeArrayAndPropertiesPair = createStyleBasedTypedArray(style, attrs); - mTypedArrayCache.put(attrs, currentThemes, resId, typeArrayAndPropertiesPair); - } - // Add value to defaultPropsMap if needed - if (typeArrayAndPropertiesPair.getSecond() != null) { - BridgeXmlBlockParser parser = getCurrentParser(); - Object key = parser != null ? parser.getViewCookie() : null; - if (key != null) { - PropertiesMap defaultPropMap = mDefaultPropMaps.get(key); - if (defaultPropMap == null) { - defaultPropMap = typeArrayAndPropertiesPair.getSecond(); - mDefaultPropMaps.put(key, defaultPropMap); - } else { - defaultPropMap.putAll(typeArrayAndPropertiesPair.getSecond()); - } - } - } - return typeArrayAndPropertiesPair.getFirst(); - } - - @Override - public final BridgeTypedArray obtainStyledAttributes(AttributeSet set, int[] attrs) { - return obtainStyledAttributes(set, attrs, 0, 0); - } - - @Override - public BridgeTypedArray obtainStyledAttributes(AttributeSet set, int[] attrs, - int defStyleAttr, int defStyleRes) { - - PropertiesMap defaultPropMap = null; - boolean isPlatformFile = true; - - // Hint: for XmlPullParser, attach source //DEVICE_SRC/dalvik/libcore/xml/src/java - if (set instanceof BridgeXmlBlockParser) { - BridgeXmlBlockParser parser; - parser = (BridgeXmlBlockParser)set; - - isPlatformFile = parser.isPlatformFile(); - - Object key = parser.getViewCookie(); - if (key != null) { - defaultPropMap = mDefaultPropMaps.computeIfAbsent(key, k -> new PropertiesMap()); - } - - } else if (set instanceof BridgeLayoutParamsMapAttributes) { - // this is only for temp layout params generated dynamically, so this is never - // platform content. - isPlatformFile = false; - } else if (set != null) { // null parser is ok - // really this should not be happening since its instantiated in Bridge - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "Parser is not a BridgeXmlBlockParser!", null); - return null; - } - - List<Pair<String, Boolean>> attributeList = searchAttrs(attrs); - - BridgeTypedArray ta = - Resources_Delegate.newTypeArray(mSystemResources, attrs.length, isPlatformFile); - - // look for a custom style. - String customStyle = null; - if (set != null) { - customStyle = set.getAttributeValue(null, "style"); - } - - StyleResourceValue customStyleValues = null; - if (customStyle != null) { - ResourceValue item = mRenderResources.findResValue(customStyle, - isPlatformFile /*forceFrameworkOnly*/); - - // resolve it in case it links to something else - item = mRenderResources.resolveResValue(item); - - if (item instanceof StyleResourceValue) { - customStyleValues = (StyleResourceValue)item; - } - } - - // resolve the defStyleAttr value into a IStyleResourceValue - StyleResourceValue defStyleValues = null; - - if (defStyleAttr != 0) { - // get the name from the int. - Pair<String, Boolean> defStyleAttribute = searchAttr(defStyleAttr); - - if (defStyleAttribute == null) { - // This should be rare. Happens trying to map R.style.foo to @style/foo fails. - // This will happen if the user explicitly used a non existing int value for - // defStyleAttr or there's something wrong with the project structure/build. - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE, - "Failed to find the style corresponding to the id " + defStyleAttr, null); - } else { - String defStyleName = defStyleAttribute.getFirst(); - - // look for the style in the current theme, and its parent: - ResourceValue item = mRenderResources.findItemInTheme(defStyleName, - defStyleAttribute.getSecond()); - - if (item != null) { - // item is a reference to a style entry. Search for it. - item = mRenderResources.findResValue(item.getValue(), item.isFramework()); - item = mRenderResources.resolveResValue(item); - if (item instanceof StyleResourceValue) { - defStyleValues = (StyleResourceValue) item; - } - if (defaultPropMap != null) { - if (defStyleAttribute.getSecond()) { - defStyleName = "android:" + defStyleName; - } - defaultPropMap.put("style", new Property(defStyleName, item.getValue())); - } - } else { - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR, - String.format( - "Failed to find style '%s' in current theme", - defStyleAttribute.getFirst()), - null); - } - } - } else if (defStyleRes != 0) { - StyleResourceValue item = getStyleByDynamicId(defStyleRes); - if (item != null) { - defStyleValues = item; - } else { - boolean isFrameworkRes = true; - Pair<ResourceType, String> value = Bridge.resolveResourceId(defStyleRes); - if (value == null) { - value = mLayoutlibCallback.resolveResourceId(defStyleRes); - isFrameworkRes = false; - } - - if (value != null) { - if ((value.getFirst() == ResourceType.STYLE)) { - // look for the style in all resources: - item = mRenderResources.getStyle(value.getSecond(), isFrameworkRes); - if (item != null) { - if (defaultPropMap != null) { - String name = item.getName(); - defaultPropMap.put("style", new Property(name, name)); - } - - defStyleValues = item; - } else { - Bridge.getLog().error(null, - String.format( - "Style with id 0x%x (resolved to '%s') does not exist.", - defStyleRes, value.getSecond()), - null); - } - } else { - Bridge.getLog().error(null, - String.format( - "Resource id 0x%x is not of type STYLE (instead %s)", - defStyleRes, value.getFirst().toString()), - null); - } - } else { - Bridge.getLog().error(null, - String.format( - "Failed to find style with id 0x%x in current theme", - defStyleRes), - null); - } - } - } - - String appNamespace = mLayoutlibCallback.getNamespace(); - - if (attributeList != null) { - for (int index = 0 ; index < attributeList.size() ; index++) { - Pair<String, Boolean> attribute = attributeList.get(index); - - if (attribute == null) { - continue; - } - - String attrName = attribute.getFirst(); - boolean frameworkAttr = attribute.getSecond(); - String value = null; - if (set != null) { - value = set.getAttributeValue( - frameworkAttr ? BridgeConstants.NS_RESOURCES : appNamespace, - attrName); - - // if this is an app attribute, and the first get fails, try with the - // new res-auto namespace as well - if (!frameworkAttr && value == null) { - value = set.getAttributeValue(BridgeConstants.NS_APP_RES_AUTO, attrName); - } - } - - // Calculate the default value from the Theme in two cases: - // - If defaultPropMap is not null, get the default value to add it to the list - // of default values of properties. - // - If value is null, it means that the attribute is not directly set as an - // attribute in the XML so try to get the default value. - ResourceValue defaultValue = null; - if (defaultPropMap != null || value == null) { - // look for the value in the custom style first (and its parent if needed) - if (customStyleValues != null) { - defaultValue = mRenderResources.findItemInStyle(customStyleValues, attrName, - frameworkAttr); - } - - // then look for the value in the default Style (and its parent if needed) - if (defaultValue == null && defStyleValues != null) { - defaultValue = mRenderResources.findItemInStyle(defStyleValues, attrName, - frameworkAttr); - } - - // if the item is not present in the defStyle, we look in the main theme (and - // its parent themes) - if (defaultValue == null) { - defaultValue = mRenderResources.findItemInTheme(attrName, frameworkAttr); - } - - // if we found a value, we make sure this doesn't reference another value. - // So we resolve it. - if (defaultValue != null) { - String preResolve = defaultValue.getValue(); - defaultValue = mRenderResources.resolveResValue(defaultValue); - - if (defaultPropMap != null) { - defaultPropMap.put( - frameworkAttr ? SdkConstants.PREFIX_ANDROID + attrName : - attrName, new Property(preResolve, defaultValue.getValue())); - } - } - } - // Done calculating the defaultValue - - // if there's no direct value for this attribute in the XML, we look for default - // values in the widget defStyle, and then in the theme. - if (value == null) { - if (frameworkAttr) { - // For some framework values, layoutlib patches the actual value in the - // theme when it helps to improve the final preview. In most cases - // we just disable animations. - ResourceValue patchedValue = FRAMEWORK_PATCHED_VALUES.get(attrName); - if (patchedValue != null) { - defaultValue = patchedValue; - } - } - - // if we found a value, we make sure this doesn't reference another value. - // So we resolve it. - if (defaultValue != null) { - // If the value is a reference to another theme attribute that doesn't - // exist, we should log a warning and omit it. - String val = defaultValue.getValue(); - if (val != null && val.startsWith(SdkConstants.PREFIX_THEME_REF)) { - // Because we always use the latest framework code, some resources might - // fail to resolve when using old themes (they haven't been backported). - // Since this is an artifact caused by us using always the latest - // code, we check for some of those values and replace them here. - defaultValue = FRAMEWORK_REPLACE_VALUES.get(attrName); - - if (defaultValue == null && - (getApplicationInfo().targetSdkVersion < JELLY_BEAN_MR1 || - !attrName.equals(RTL_ATTRS.get(val)))) { - // Only log a warning if the referenced value isn't one of the RTL - // attributes, or the app targets old API. - Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR, - String.format("Failed to find '%s' in current theme.", val), - val); - } - } - } - - ta.bridgeSetValue(index, attrName, frameworkAttr, defaultValue); - } else { - // there is a value in the XML, but we need to resolve it in case it's - // referencing another resource or a theme value. - ta.bridgeSetValue(index, attrName, frameworkAttr, - mRenderResources.resolveValue(null, attrName, value, isPlatformFile)); - } - } - } - - ta.sealArray(); - - return ta; - } - - @Override - public Looper getMainLooper() { - return Looper.myLooper(); - } - - - @Override - public String getPackageName() { - if (mApplicationInfo.packageName == null) { - mApplicationInfo.packageName = mLayoutlibCallback.getFlag(FLAG_KEY_APPLICATION_PACKAGE); - } - return mApplicationInfo.packageName; - } - - @Override - public PackageManager getPackageManager() { - if (mPackageManager == null) { - mPackageManager = new BridgePackageManager(); - } - return mPackageManager; - } - - // ------------- private new methods - - /** - * Creates a {@link BridgeTypedArray} by filling the values defined by the int[] with the - * values found in the given style. If no style is specified, the default theme, along with the - * styles applied to it are used. - * - * @see #obtainStyledAttributes(int, int[]) - */ - private Pair<BridgeTypedArray, PropertiesMap> createStyleBasedTypedArray( - @Nullable StyleResourceValue style, int[] attrs) throws Resources.NotFoundException { - List<Pair<String, Boolean>> attributes = searchAttrs(attrs); - - BridgeTypedArray ta = - Resources_Delegate.newTypeArray(mSystemResources, attrs.length, false); - - PropertiesMap defaultPropMap = new PropertiesMap(); - // for each attribute, get its name so that we can search it in the style - for (int i = 0; i < attrs.length; i++) { - Pair<String, Boolean> attribute = attributes.get(i); - - if (attribute != null) { - // look for the value in the given style - ResourceValue resValue; - String attrName = attribute.getFirst(); - boolean frameworkAttr = attribute.getSecond(); - if (style != null) { - resValue = mRenderResources.findItemInStyle(style, attrName, frameworkAttr); - } else { - resValue = mRenderResources.findItemInTheme(attrName, frameworkAttr); - } - - if (resValue != null) { - // Add it to defaultPropMap before resolving - String preResolve = resValue.getValue(); - // resolve it to make sure there are no references left. - resValue = mRenderResources.resolveResValue(resValue); - ta.bridgeSetValue(i, attrName, frameworkAttr, resValue); - defaultPropMap.put( - frameworkAttr ? SdkConstants.ANDROID_PREFIX + attrName : attrName, - new Property(preResolve, resValue.getValue())); - } - } - } - - ta.sealArray(); - - return Pair.of(ta, defaultPropMap); - } - - /** - * The input int[] attrs is a list of attributes. The returns a list of information about - * each attributes. The information is (name, isFramework) - * <p/> - * - * @param attrs An attribute array reference given to obtainStyledAttributes. - * @return List of attribute information. - */ - private List<Pair<String, Boolean>> searchAttrs(int[] attrs) { - List<Pair<String, Boolean>> results = new ArrayList<>(attrs.length); - - // for each attribute, get its name so that we can search it in the style - for (int attr : attrs) { - Pair<ResourceType, String> resolvedResource = Bridge.resolveResourceId(attr); - boolean isFramework = false; - if (resolvedResource != null) { - isFramework = true; - } else { - resolvedResource = mLayoutlibCallback.resolveResourceId(attr); - } - - if (resolvedResource != null) { - results.add(Pair.of(resolvedResource.getSecond(), isFramework)); - } else { - results.add(null); - } - } - - return results; - } - - /** - * Searches for the attribute referenced by its internal id. - * - * @param attr An attribute reference given to obtainStyledAttributes such as defStyle. - * @return A (name, isFramework) pair describing the attribute if found. Returns null - * if nothing is found. - */ - private Pair<String, Boolean> searchAttr(int attr) { - Pair<ResourceType, String> info = Bridge.resolveResourceId(attr); - if (info != null) { - return Pair.of(info.getSecond(), Boolean.TRUE); - } - - info = mLayoutlibCallback.resolveResourceId(attr); - if (info != null) { - return Pair.of(info.getSecond(), Boolean.FALSE); - } - - return null; - } - - public int getDynamicIdByStyle(StyleResourceValue resValue) { - if (mDynamicIdToStyleMap == null) { - // create the maps. - mDynamicIdToStyleMap = new HashMap<>(); - mStyleToDynamicIdMap = new HashMap<>(); - } - - // look for an existing id - Integer id = mStyleToDynamicIdMap.get(resValue); - - if (id == null) { - // generate a new id - id = ++mDynamicIdGenerator; - - // and add it to the maps. - mDynamicIdToStyleMap.put(id, resValue); - mStyleToDynamicIdMap.put(resValue, id); - } - - return id; - } - - private StyleResourceValue getStyleByDynamicId(int i) { - if (mDynamicIdToStyleMap != null) { - return mDynamicIdToStyleMap.get(i); - } - - return null; - } - - public int getFrameworkResourceValue(ResourceType resType, String resName, int defValue) { - if (getRenderResources().getFrameworkResource(resType, resName) != null) { - // Bridge.getResourceId creates a new resource id if an existing one isn't found. So, - // we check for the existence of the resource before calling it. - return Bridge.getResourceId(resType, resName); - } - - return defValue; - } - - public int getProjectResourceValue(ResourceType resType, String resName, int defValue) { - // getResourceId creates a new resource id if an existing resource id isn't found. So, we - // check for the existence of the resource before calling it. - if (getRenderResources().getProjectResource(resType, resName) != null) { - if (mLayoutlibCallback != null) { - Integer value = mLayoutlibCallback.getResourceId(resType, resName); - if (value != null) { - return value; - } - } - } - - return defValue; - } - - public static Context getBaseContext(Context context) { - while (context instanceof ContextWrapper) { - context = ((ContextWrapper) context).getBaseContext(); - } - return context; - } - - public IBinder getBinder() { - if (mBinder == null) { - // create a dummy binder. We only need it be not null. - mBinder = new IBinder() { - @Override - public String getInterfaceDescriptor() throws RemoteException { - return null; - } - - @Override - public boolean pingBinder() { - return false; - } - - @Override - public boolean isBinderAlive() { - return false; - } - - @Override - public IInterface queryLocalInterface(String descriptor) { - return null; - } - - @Override - public void dump(FileDescriptor fd, String[] args) throws RemoteException { - - } - - @Override - public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException { - - } - - @Override - public boolean transact(int code, Parcel data, Parcel reply, int flags) - throws RemoteException { - return false; - } - - @Override - public void linkToDeath(DeathRecipient recipient, int flags) - throws RemoteException { - - } - - @Override - public boolean unlinkToDeath(DeathRecipient recipient, int flags) { - return false; - } - - @Override - public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, - String[] args, ShellCallback shellCallback, ResultReceiver resultReceiver) { - } - }; - } - return mBinder; - } - - //------------ NOT OVERRIDEN -------------------- - - @Override - public boolean bindService(Intent arg0, ServiceConnection arg1, int arg2) { - // pass - return false; - } - - @Override - public int checkCallingOrSelfPermission(String arg0) { - // pass - return 0; - } - - @Override - public int checkCallingOrSelfUriPermission(Uri arg0, int arg1) { - // pass - return 0; - } - - @Override - public int checkCallingPermission(String arg0) { - // pass - return 0; - } - - @Override - public int checkCallingUriPermission(Uri arg0, int arg1) { - // pass - return 0; - } - - @Override - public int checkPermission(String arg0, int arg1, int arg2) { - // pass - return 0; - } - - @Override - public int checkSelfPermission(String arg0) { - // pass - return 0; - } - - @Override - public int checkPermission(String arg0, int arg1, int arg2, IBinder arg3) { - // pass - return 0; - } - - @Override - public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3) { - // pass - return 0; - } - - @Override - public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3, IBinder arg4) { - // pass - return 0; - } - - @Override - public int checkUriPermission(Uri arg0, String arg1, String arg2, int arg3, - int arg4, int arg5) { - // pass - return 0; - } - - @Override - public void clearWallpaper() { - // pass - - } - - @Override - public Context createPackageContext(String arg0, int arg1) { - // pass - return null; - } - - @Override - public Context createPackageContextAsUser(String arg0, int arg1, UserHandle user) { - // pass - return null; - } - - @Override - public Context createConfigurationContext(Configuration overrideConfiguration) { - // pass - return null; - } - - @Override - public Context createDisplayContext(Display display) { - // pass - return null; - } - - @Override - public Context createContextForSplit(String splitName) { - // pass - return null; - } - - @Override - public String[] databaseList() { - // pass - return null; - } - - @Override - public Context createApplicationContext(ApplicationInfo application, int flags) - throws PackageManager.NameNotFoundException { - return null; - } - - @Override - public boolean moveDatabaseFrom(Context sourceContext, String name) { - // pass - return false; - } - - @Override - public boolean deleteDatabase(String arg0) { - // pass - return false; - } - - @Override - public boolean deleteFile(String arg0) { - // pass - return false; - } - - @Override - public void enforceCallingOrSelfPermission(String arg0, String arg1) { - // pass - - } - - @Override - public void enforceCallingOrSelfUriPermission(Uri arg0, int arg1, - String arg2) { - // pass - - } - - @Override - public void enforceCallingPermission(String arg0, String arg1) { - // pass - - } - - @Override - public void enforceCallingUriPermission(Uri arg0, int arg1, String arg2) { - // pass - - } - - @Override - public void enforcePermission(String arg0, int arg1, int arg2, String arg3) { - // pass - - } - - @Override - public void enforceUriPermission(Uri arg0, int arg1, int arg2, int arg3, - String arg4) { - // pass - - } - - @Override - public void enforceUriPermission(Uri arg0, String arg1, String arg2, - int arg3, int arg4, int arg5, String arg6) { - // pass - - } - - @Override - public String[] fileList() { - // pass - return null; - } - - @Override - public BridgeAssetManager getAssets() { - return mAssets; - } - - @Override - public File getCacheDir() { - // pass - return null; - } - - @Override - public File getCodeCacheDir() { - // pass - return null; - } - - @Override - public File getExternalCacheDir() { - // pass - return null; - } - - @Override - public File getPreloadsFileCache() { - // pass - return null; - } - - @Override - public ContentResolver getContentResolver() { - if (mContentResolver == null) { - mContentResolver = new BridgeContentResolver(this); - } - return mContentResolver; - } - - @Override - public File getDatabasePath(String arg0) { - // pass - return null; - } - - @Override - public File getDir(String arg0, int arg1) { - // pass - return null; - } - - @Override - public File getFileStreamPath(String arg0) { - // pass - return null; - } - - @Override - public File getSharedPreferencesPath(String name) { - // pass - return null; - } - - @Override - public File getDataDir() { - // pass - return null; - } - - @Override - public File getFilesDir() { - // pass - return null; - } - - @Override - public File getNoBackupFilesDir() { - // pass - return null; - } - - @Override - public File getExternalFilesDir(String type) { - // pass - return null; - } - - @Override - public String getPackageCodePath() { - // pass - return null; - } - - @Override - public String getBasePackageName() { - // pass - return null; - } - - @Override - public String getOpPackageName() { - // pass - return null; - } - - @Override - public ApplicationInfo getApplicationInfo() { - return mApplicationInfo; - } - - @Override - public String getPackageResourcePath() { - // pass - return null; - } - - @Override - public SharedPreferences getSharedPreferences(String arg0, int arg1) { - if (mSharedPreferences == null) { - mSharedPreferences = new BridgeSharedPreferences(); - } - return mSharedPreferences; - } - - @Override - public SharedPreferences getSharedPreferences(File arg0, int arg1) { - if (mSharedPreferences == null) { - mSharedPreferences = new BridgeSharedPreferences(); - } - return mSharedPreferences; - } - - @Override - public boolean moveSharedPreferencesFrom(Context sourceContext, String name) { - // pass - return false; - } - - @Override - public boolean deleteSharedPreferences(String name) { - // pass - return false; - } - - @Override - public Drawable getWallpaper() { - // pass - return null; - } - - @Override - public int getWallpaperDesiredMinimumWidth() { - return -1; - } - - @Override - public int getWallpaperDesiredMinimumHeight() { - return -1; - } - - @Override - public void grantUriPermission(String arg0, Uri arg1, int arg2) { - // pass - - } - - @Override - public FileInputStream openFileInput(String arg0) throws FileNotFoundException { - // pass - return null; - } - - @Override - public FileOutputStream openFileOutput(String arg0, int arg1) throws FileNotFoundException { - // pass - return null; - } - - @Override - public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2) { - // pass - return null; - } - - @Override - public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1, - CursorFactory arg2, DatabaseErrorHandler arg3) { - // pass - return null; - } - - @Override - public Drawable peekWallpaper() { - // pass - return null; - } - - @Override - public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1) { - // pass - return null; - } - - @Override - public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, int arg2) { - // pass - return null; - } - - @Override - public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, - String arg2, Handler arg3) { - // pass - return null; - } - - @Override - public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, - String arg2, Handler arg3, int arg4) { - // pass - return null; - } - - @Override - public Intent registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5, - IntentFilter arg1, String arg2, Handler arg3) { - // pass - return null; - } - - @Override - public void removeStickyBroadcast(Intent arg0) { - // pass - - } - - @Override - public void revokeUriPermission(Uri arg0, int arg1) { - // pass - - } - - @Override - public void revokeUriPermission(String arg0, Uri arg1, int arg2) { - // pass - - } - - @Override - public void sendBroadcast(Intent arg0) { - // pass - - } - - @Override - public void sendBroadcast(Intent arg0, String arg1) { - // pass - - } - - @Override - public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions) { - // pass - - } - - @Override - public void sendBroadcast(Intent arg0, String arg1, Bundle arg2) { - // pass - - } - - @Override - public void sendBroadcast(Intent intent, String receiverPermission, int appOp) { - // pass - } - - @Override - public void sendOrderedBroadcast(Intent arg0, String arg1) { - // pass - - } - - @Override - public void sendOrderedBroadcast(Intent arg0, String arg1, - BroadcastReceiver arg2, Handler arg3, int arg4, String arg5, - Bundle arg6) { - // pass - - } - - @Override - public void sendOrderedBroadcast(Intent arg0, String arg1, - Bundle arg7, BroadcastReceiver arg2, Handler arg3, int arg4, String arg5, - Bundle arg6) { - // pass - - } - - @Override - public void sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp, - BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, - String initialData, Bundle initialExtras) { - // pass - } - - @Override - public void sendBroadcastAsUser(Intent intent, UserHandle user) { - // pass - } - - @Override - public void sendBroadcastAsUser(Intent intent, UserHandle user, - String receiverPermission) { - // pass - } - - @Override - public void sendBroadcastAsUser(Intent intent, UserHandle user, - String receiverPermission, Bundle options) { - // pass - } - - public void sendBroadcastAsUser(Intent intent, UserHandle user, - String receiverPermission, int appOp) { - // pass - } - - @Override - public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, - String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, - int initialCode, String initialData, Bundle initialExtras) { - // pass - } - - @Override - public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, - String receiverPermission, int appOp, BroadcastReceiver resultReceiver, - Handler scheduler, - int initialCode, String initialData, Bundle initialExtras) { - // pass - } - - @Override - public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, - String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver, - Handler scheduler, - int initialCode, String initialData, Bundle initialExtras) { - // pass - } - - @Override - public void sendStickyBroadcast(Intent arg0) { - // pass - - } - - @Override - public void sendStickyOrderedBroadcast(Intent intent, - BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, - Bundle initialExtras) { - // pass - } - - @Override - public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) { - // pass - } - - @Override - public void sendStickyBroadcastAsUser(Intent intent, UserHandle user, Bundle options) { - // pass - } - - @Override - public void sendStickyOrderedBroadcastAsUser(Intent intent, - UserHandle user, BroadcastReceiver resultReceiver, - Handler scheduler, int initialCode, String initialData, - Bundle initialExtras) { - // pass - } - - @Override - public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) { - // pass - } - - @Override - public void setTheme(int arg0) { - // pass - - } - - @Override - public void setWallpaper(Bitmap arg0) throws IOException { - // pass - - } - - @Override - public void setWallpaper(InputStream arg0) throws IOException { - // pass - - } - - @Override - public void startActivity(Intent arg0) { - // pass - } - - @Override - public void startActivity(Intent arg0, Bundle arg1) { - // pass - } - - @Override - public void startIntentSender(IntentSender intent, - Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags) - throws IntentSender.SendIntentException { - // pass - } - - @Override - public void startIntentSender(IntentSender intent, - Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, - Bundle options) throws IntentSender.SendIntentException { - // pass - } - - @Override - public boolean startInstrumentation(ComponentName arg0, String arg1, - Bundle arg2) { - // pass - return false; - } - - @Override - public ComponentName startService(Intent arg0) { - // pass - return null; - } - - @Override - public ComponentName startForegroundService(Intent service) { - // pass - return null; - } - - @Override - public ComponentName startForegroundServiceAsUser(Intent service, UserHandle user) { - // pass - return null; - } - - @Override - public boolean stopService(Intent arg0) { - // pass - return false; - } - - @Override - public ComponentName startServiceAsUser(Intent arg0, UserHandle arg1) { - // pass - return null; - } - - @Override - public boolean stopServiceAsUser(Intent arg0, UserHandle arg1) { - // pass - return false; - } - - @Override - public void unbindService(ServiceConnection arg0) { - // pass - - } - - @Override - public void unregisterReceiver(BroadcastReceiver arg0) { - // pass - - } - - @Override - public Context getApplicationContext() { - return this; - } - - @Override - public void startActivities(Intent[] arg0) { - // pass - - } - - @Override - public void startActivities(Intent[] arg0, Bundle arg1) { - // pass - - } - - @Override - public boolean isRestricted() { - return false; - } - - @Override - public File getObbDir() { - Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, "OBB not supported", null); - return null; - } - - @Override - public DisplayAdjustments getDisplayAdjustments(int displayId) { - // pass - return null; - } - - @Override - public Display getDisplay() { - // pass - return null; - } - - @Override - public void updateDisplay(int displayId) { - // pass - } - - @Override - public int getUserId() { - return 0; // not used - } - - @Override - public File[] getExternalFilesDirs(String type) { - // pass - return new File[0]; - } - - @Override - public File[] getObbDirs() { - // pass - return new File[0]; - } - - @Override - public File[] getExternalCacheDirs() { - // pass - return new File[0]; - } - - @Override - public File[] getExternalMediaDirs() { - // pass - return new File[0]; - } - - public void setScrollYPos(@NonNull View view, int scrollPos) { - mScrollYPos.put(view, scrollPos); - } - - public int getScrollYPos(@NonNull View view) { - Integer pos = mScrollYPos.get(view); - return pos != null ? pos : 0; - } - - public void setScrollXPos(@NonNull View view, int scrollPos) { - mScrollXPos.put(view, scrollPos); - } - - public int getScrollXPos(@NonNull View view) { - Integer pos = mScrollXPos.get(view); - return pos != null ? pos : 0; - } - - @Override - public Context createDeviceProtectedStorageContext() { - // pass - return null; - } - - @Override - public Context createCredentialProtectedStorageContext() { - // pass - return null; - } - - @Override - public boolean isDeviceProtectedStorage() { - return false; - } - - @Override - public boolean isCredentialProtectedStorage() { - return false; - } - - /** - * The cached value depends on - * <ol> - * <li>{@code int[]}: the attributes for which TypedArray is created </li> - * <li>{@code List<StyleResourceValue>}: the themes set on the context at the time of - * creation of the TypedArray</li> - * <li>{@code Integer}: the default style used at the time of creation</li> - * </ol> - * - * The class is created by using nested maps resolving one dependency at a time. - * <p/> - * The final value of the nested maps is a pair of the typed array and a map of properties - * that should be added to {@link #mDefaultPropMaps}, if needed. - */ - private static class TypedArrayCache { - - private Map<int[], - Map<List<StyleResourceValue>, - Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>>> mCache; - - private TypedArrayCache() { - mCache = new IdentityHashMap<>(); - } - - public Pair<BridgeTypedArray, PropertiesMap> get(int[] attrs, - List<StyleResourceValue> themes, int resId) { - Map<List<StyleResourceValue>, Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>> - cacheFromThemes = mCache.get(attrs); - if (cacheFromThemes != null) { - Map<Integer, Pair<BridgeTypedArray, PropertiesMap>> cacheFromResId = - cacheFromThemes.get(themes); - if (cacheFromResId != null) { - return cacheFromResId.get(resId); - } - } - return null; - } - - public void put(int[] attrs, List<StyleResourceValue> themes, int resId, - Pair<BridgeTypedArray, PropertiesMap> value) { - Map<List<StyleResourceValue>, Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>> - cacheFromThemes = mCache.computeIfAbsent(attrs, k -> new HashMap<>()); - Map<Integer, Pair<BridgeTypedArray, PropertiesMap>> cacheFromResId = - cacheFromThemes.computeIfAbsent(themes, k -> new HashMap<>()); - cacheFromResId.put(resId, value); - } - - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java deleted file mode 100644 index 4805ed1e61b7..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.android; - -import com.android.internal.inputmethod.IInputContentUriToken; -import com.android.internal.view.IInputContext; -import com.android.internal.view.IInputMethodClient; -import com.android.internal.view.IInputMethodManager; -import com.android.internal.view.InputBindResult; - -import android.net.Uri; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.ResultReceiver; -import android.text.style.SuggestionSpan; -import android.view.inputmethod.EditorInfo; -import android.view.inputmethod.InputMethodInfo; -import android.view.inputmethod.InputMethodSubtype; - -import java.util.List; - -/** - * Basic implementation of IInputMethodManager that does nothing. - * - */ -public class BridgeIInputMethodManager implements IInputMethodManager { - - @Override - public void addClient(IInputMethodClient arg0, IInputContext arg1, int arg2, int arg3) - throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void finishInput(IInputMethodClient arg0) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public InputMethodSubtype getCurrentInputMethodSubtype() throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public List<InputMethodInfo> getEnabledInputMethodList() throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(String arg0, - boolean arg1) throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public List<InputMethodInfo> getInputMethodList() throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public InputMethodSubtype getLastInputMethodSubtype() throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public List getShortcutInputMethodsAndSubtypes() throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public void hideMySoftInput(IBinder arg0, int arg1) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public boolean hideSoftInput(IInputMethodClient arg0, int arg1, ResultReceiver arg2) - throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean notifySuggestionPicked(SuggestionSpan arg0, String arg1, int arg2) - throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public void registerSuggestionSpansForNotification(SuggestionSpan[] arg0) - throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void removeClient(IInputMethodClient arg0) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void setAdditionalInputMethodSubtypes(String arg0, InputMethodSubtype[] arg1) - throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public boolean setCurrentInputMethodSubtype(InputMethodSubtype arg0) throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public void setImeWindowStatus(IBinder arg0, IBinder arg1, int arg2, int arg3) - throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void setInputMethod(IBinder arg0, String arg1) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void setInputMethodAndSubtype(IBinder arg0, String arg1, InputMethodSubtype arg2) - throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public boolean setInputMethodEnabled(String arg0, boolean arg1) throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public void showInputMethodAndSubtypeEnablerFromClient(IInputMethodClient arg0, String arg1) - throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void showInputMethodPickerFromClient(IInputMethodClient arg0, - int arg1) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void showMySoftInput(IBinder arg0, int arg1) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public boolean showSoftInput(IInputMethodClient arg0, int arg1, ResultReceiver arg2) - throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean switchToLastInputMethod(IBinder arg0) throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean switchToNextInputMethod(IBinder arg0, boolean arg1) throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean shouldOfferSwitchingToNextInputMethod(IBinder arg0) throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public int getInputMethodWindowVisibleHeight() throws RemoteException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public void notifyUserAction(int sequenceNumber) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void updateStatusIcon(IBinder arg0, String arg1, int arg2) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void clearLastInputMethodWindowForTransition(IBinder arg0) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public InputBindResult startInputOrWindowGainedFocus( - /* @InputMethodClient.StartInputReason */ int startInputReason, - IInputMethodClient client, IBinder windowToken, int controlFlags, - /* @android.view.WindowManager.LayoutParams.SoftInputModeFlags */ int softInputMode, - int windowFlags, EditorInfo attribute, IInputContext inputContext, - /* @InputConnectionInspector.MissingMethodFlags */ int missingMethodFlags) - throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public IBinder asBinder() { - // TODO Auto-generated method stub - return null; - } - - @Override - public IInputContentUriToken createInputContentUriToken(IBinder token, Uri contentUri, - String packageName) { - // TODO Auto-generated method stub - return null; - } - - @Override - public void reportFullscreenMode(IBinder token, boolean fullscreen) { - // TODO Auto-generated method stub - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeLayoutParamsMapAttributes.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeLayoutParamsMapAttributes.java deleted file mode 100644 index f5912e7bdb24..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeLayoutParamsMapAttributes.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.android; - -import com.android.layoutlib.bridge.BridgeConstants; - -import android.util.AttributeSet; - -import java.util.Map; - -/** - * An implementation of the {@link AttributeSet} interface on top of a map of attribute in the form - * of (name, value). - * - * This is meant to be called only from {@link BridgeContext#obtainStyledAttributes(AttributeSet, int[], int, int)} - * in the case of LayoutParams and therefore isn't a full implementation. - */ -public class BridgeLayoutParamsMapAttributes implements AttributeSet { - - private final Map<String, String> mAttributes; - - public BridgeLayoutParamsMapAttributes(Map<String, String> attributes) { - mAttributes = attributes; - } - - @Override - public String getAttributeValue(String namespace, String name) { - if (BridgeConstants.NS_RESOURCES.equals(namespace)) { - return mAttributes.get(name); - } - - return null; - } - - // ---- the following methods are not called from - // BridgeContext#obtainStyledAttributes(AttributeSet, int[], int, int) - // Should they ever be called, we'll just implement them on a need basis. - - @Override - public int getAttributeCount() { - throw new UnsupportedOperationException(); - } - - @Override - public String getAttributeName(int index) { - throw new UnsupportedOperationException(); - } - - @Override - public String getAttributeValue(int index) { - throw new UnsupportedOperationException(); - } - - @Override - public String getPositionDescription() { - throw new UnsupportedOperationException(); - } - - @Override - public int getAttributeNameResource(int index) { - throw new UnsupportedOperationException(); - } - - @Override - public int getAttributeListValue(String namespace, String attribute, - String[] options, int defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean getAttributeBooleanValue(String namespace, String attribute, - boolean defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public int getAttributeResourceValue(String namespace, String attribute, - int defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public int getAttributeIntValue(String namespace, String attribute, - int defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public int getAttributeUnsignedIntValue(String namespace, String attribute, - int defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public float getAttributeFloatValue(String namespace, String attribute, - float defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public int getAttributeListValue(int index, - String[] options, int defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean getAttributeBooleanValue(int index, boolean defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public int getAttributeResourceValue(int index, int defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public int getAttributeIntValue(int index, int defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public int getAttributeUnsignedIntValue(int index, int defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public float getAttributeFloatValue(int index, float defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public String getIdAttribute() { - throw new UnsupportedOperationException(); - } - - @Override - public String getClassAttribute() { - throw new UnsupportedOperationException(); - } - - @Override - public int getIdAttributeResourceValue(int defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public int getStyleAttribute() { - throw new UnsupportedOperationException(); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java deleted file mode 100644 index 47dad3404beb..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java +++ /dev/null @@ -1,958 +0,0 @@ -/* - * 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 com.android.layoutlib.bridge.android; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.app.PackageInstallObserver; -import android.content.ComponentName; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.IntentSender; -import android.content.pm.ActivityInfo; -import android.content.pm.ApplicationInfo; -import android.content.pm.ChangedPackages; -import android.content.pm.InstantAppInfo; -import android.content.pm.FeatureInfo; -import android.content.pm.IPackageDataObserver; -import android.content.pm.IPackageDeleteObserver; -import android.content.pm.IPackageInstallObserver; -import android.content.pm.IPackageStatsObserver; -import android.content.pm.InstrumentationInfo; -import android.content.pm.IntentFilterVerificationInfo; -import android.content.pm.KeySet; -import android.content.pm.PackageInfo; -import android.content.pm.PackageInstaller; -import android.content.pm.PackageItemInfo; -import android.content.pm.PackageManager; -import android.content.pm.PermissionGroupInfo; -import android.content.pm.PermissionInfo; -import android.content.pm.ProviderInfo; -import android.content.pm.ResolveInfo; -import android.content.pm.ServiceInfo; -import android.content.pm.SharedLibraryInfo; -import android.content.pm.VerifierDeviceIdentity; -import android.content.pm.VersionedPackage; -import android.content.res.Resources; -import android.content.res.XmlResourceParser; -import android.graphics.Rect; -import android.graphics.drawable.ColorDrawable; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.Handler; -import android.os.UserHandle; -import android.os.storage.VolumeInfo; -import java.util.List; - -/** - * An implementation of {@link PackageManager} that does nothing. - */ -@SuppressWarnings("deprecation") -public class BridgePackageManager extends PackageManager { - @Override - public PackageInfo getPackageInfo(String packageName, int flags) throws NameNotFoundException { - return null; - } - - @Override - public PackageInfo getPackageInfoAsUser(String packageName, int flags, int userId) - throws NameNotFoundException { - return null; - } - - @Override - public PackageInfo getPackageInfo(VersionedPackage versionedPackage, - @PackageInfoFlags int flags) throws NameNotFoundException { - return null; - } - - @Override - public List<SharedLibraryInfo> getSharedLibraries(@InstallFlags int flags) { - return null; - } - - @Override - public List<SharedLibraryInfo> getSharedLibrariesAsUser(@InstallFlags int flags, - int userId) { - return null; - } - - @Override - public String[] currentToCanonicalPackageNames(String[] names) { - return new String[0]; - } - - @Override - public String[] canonicalToCurrentPackageNames(String[] names) { - return new String[0]; - } - - @Override - public Intent getLaunchIntentForPackage(String packageName) { - return null; - } - - @Override - public Intent getLeanbackLaunchIntentForPackage(String packageName) { - return null; - } - - @Override - public int[] getPackageGids(String packageName) throws NameNotFoundException { - return new int[0]; - } - - @Override - public int[] getPackageGids(String packageName, int flags) throws NameNotFoundException { - return new int[0]; - } - - @Override - public int getPackageUid(String packageName, int flags) throws NameNotFoundException { - return 0; - } - - @Override - public int getPackageUidAsUser(String packageName, int userHandle) throws NameNotFoundException { - return 0; - } - - @Override - public int getPackageUidAsUser(String packageName, int flags, int userHandle) throws NameNotFoundException { - return 0; - } - - @Override - public PermissionInfo getPermissionInfo(String name, int flags) throws NameNotFoundException { - return null; - } - - @Override - public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) - throws NameNotFoundException { - return null; - } - - @Override - public boolean isPermissionReviewModeEnabled() { - return false; - } - - @Override - public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) - throws NameNotFoundException { - return null; - } - - @Override - public List<PermissionGroupInfo> getAllPermissionGroups(int flags) { - return null; - } - - @Override - public ApplicationInfo getApplicationInfo(String packageName, int flags) - throws NameNotFoundException { - return null; - } - - @Override - public ApplicationInfo getApplicationInfoAsUser(String packageName, int flags, int userId) - throws NameNotFoundException { - return null; - } - - @Override - public ActivityInfo getActivityInfo(ComponentName component, int flags) - throws NameNotFoundException { - return null; - } - - @Override - public ActivityInfo getReceiverInfo(ComponentName component, int flags) - throws NameNotFoundException { - return null; - } - - @Override - public ServiceInfo getServiceInfo(ComponentName component, int flags) - throws NameNotFoundException { - return null; - } - - @Override - public ProviderInfo getProviderInfo(ComponentName component, int flags) - throws NameNotFoundException { - return null; - } - - @Override - public List<PackageInfo> getInstalledPackages(int flags) { - return null; - } - - @Override - public List<PackageInfo> getPackagesHoldingPermissions(String[] permissions, int flags) { - return null; - } - - @Override - public List<PackageInfo> getInstalledPackagesAsUser(int flags, int userId) { - return null; - } - - @Override - public int checkPermission(String permName, String pkgName) { - return 0; - } - - @Override - public boolean isPermissionRevokedByPolicy(String permName, String pkgName) { - return false; - } - - @Override - public String getPermissionControllerPackageName() { - return null; - } - - @Override - public boolean addPermission(PermissionInfo info) { - return false; - } - - @Override - public boolean addPermissionAsync(PermissionInfo info) { - return false; - } - - @Override - public void removePermission(String name) { - } - - @Override - public void grantRuntimePermission(String packageName, String permissionName, UserHandle user) { - } - - @Override - public void revokeRuntimePermission(String packageName, String permissionName, - UserHandle user) { - } - - @Override - public int getPermissionFlags(String permissionName, String packageName, UserHandle user) { - return 0; - } - - @Override - public void updatePermissionFlags(String permissionName, String packageName, int flagMask, - int flagValues, UserHandle user) { - } - - @Override - public boolean shouldShowRequestPermissionRationale(String permission) { - return false; - } - - @Override - public int checkSignatures(String pkg1, String pkg2) { - return 0; - } - - @Override - public int checkSignatures(int uid1, int uid2) { - return 0; - } - - @Override - public String[] getPackagesForUid(int uid) { - return new String[0]; - } - - @Override - public String getNameForUid(int uid) { - return null; - } - - @Override - public int getUidForSharedUser(String sharedUserName) throws NameNotFoundException { - return 0; - } - - @Override - public List<ApplicationInfo> getInstalledApplications(int flags) { - return null; - } - - @Override - public List<ApplicationInfo> getInstalledApplicationsAsUser(int flags, int userId) { - return null; - } - - @Override - public List<InstantAppInfo> getInstantApps() { - return null; - } - - @Override - public Drawable getInstantAppIcon(String packageName) { - assert false : "Unsupported operation"; - return new ColorDrawable(); - } - - @Override - public byte[] getInstantAppCookie() { - return new byte[0]; - } - - @Override - public boolean isInstantApp() { - return false; - } - - @Override - public boolean isInstantApp(String packageName) { - return false; - } - - @Override - public int getInstantAppCookieMaxBytes() { - return 0; - } - - @Override - public int getInstantAppCookieMaxSize() { - return 0; - } - - @Override - public void clearInstantAppCookie() {; - - } - - @Override - public void updateInstantAppCookie(@Nullable byte[] cookie) { - - } - - @Override - public boolean setInstantAppCookie(@NonNull byte[] cookie) { - return false; - } - - @Override - public String[] getSystemSharedLibraryNames() { - return new String[0]; - } - - @Override - public String getServicesSystemSharedLibraryPackageName() { - return null; - } - - @Override - public @NonNull String getSharedSystemSharedLibraryPackageName() { - return null; - } - - @Override - public FeatureInfo[] getSystemAvailableFeatures() { - return new FeatureInfo[0]; - } - - @Override - public boolean hasSystemFeature(String name) { - return false; - } - - @Override - public boolean hasSystemFeature(String name, int version) { - return false; - } - - @Override - public ResolveInfo resolveActivity(Intent intent, int flags) { - return null; - } - - @Override - public ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId) { - return null; - } - - @Override - public List<ResolveInfo> queryIntentActivities(Intent intent, int flags) { - return null; - } - - @Override - public List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent, int flags, int userId) { - return null; - } - - @Override - public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller, Intent[] specifics, - Intent intent, int flags) { - return null; - } - - @Override - public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) { - return null; - } - - @Override - public List<ResolveInfo> queryBroadcastReceiversAsUser(Intent intent, int flags, int userId) { - return null; - } - - @Override - public ResolveInfo resolveService(Intent intent, int flags) { - return null; - } - - @Override - public List<ResolveInfo> queryIntentServices(Intent intent, int flags) { - return null; - } - - @Override - public List<ResolveInfo> queryIntentServicesAsUser(Intent intent, int flags, int userId) { - return null; - } - - @Override - public List<ResolveInfo> queryIntentContentProvidersAsUser(Intent intent, int flags, - int userId) { - return null; - } - - @Override - public List<ResolveInfo> queryIntentContentProviders(Intent intent, int flags) { - return null; - } - - @Override - public ProviderInfo resolveContentProvider(String name, int flags) { - return null; - } - - @Override - public ProviderInfo resolveContentProviderAsUser(String name, int flags, int userId) { - return null; - } - - @Override - public List<ProviderInfo> queryContentProviders(String processName, int uid, int flags) { - return null; - } - - @Override - public InstrumentationInfo getInstrumentationInfo(ComponentName className, int flags) - throws NameNotFoundException { - return null; - } - - @Override - public List<InstrumentationInfo> queryInstrumentation(String targetPackage, int flags) { - return null; - } - - @Override - public Drawable getDrawable(String packageName, int resid, ApplicationInfo appInfo) { - return null; - } - - @Override - public Drawable getActivityIcon(ComponentName activityName) throws NameNotFoundException { - return null; - } - - @Override - public Drawable getActivityIcon(Intent intent) throws NameNotFoundException { - return null; - } - - @Override - public Drawable getActivityBanner(ComponentName activityName) throws NameNotFoundException { - return null; - } - - @Override - public Drawable getActivityBanner(Intent intent) throws NameNotFoundException { - return null; - } - - @Override - public Drawable getDefaultActivityIcon() { - return null; - } - - @Override - public Drawable getApplicationIcon(ApplicationInfo info) { - return null; - } - - @Override - public Drawable getApplicationIcon(String packageName) throws NameNotFoundException { - return null; - } - - @Override - public Drawable getApplicationBanner(ApplicationInfo info) { - return null; - } - - @Override - public Drawable getApplicationBanner(String packageName) throws NameNotFoundException { - return null; - } - - @Override - public Drawable getActivityLogo(ComponentName activityName) throws NameNotFoundException { - return null; - } - - @Override - public Drawable getActivityLogo(Intent intent) throws NameNotFoundException { - return null; - } - - @Override - public Drawable getApplicationLogo(ApplicationInfo info) { - return null; - } - - @Override - public Drawable getApplicationLogo(String packageName) throws NameNotFoundException { - return null; - } - - @Override - public Drawable getUserBadgedIcon(Drawable icon, UserHandle user) { - return null; - } - - @Override - public Drawable getUserBadgedDrawableForDensity(Drawable drawable, UserHandle user, - Rect badgeLocation, int badgeDensity) { - return null; - } - - @Override - public Drawable getUserBadgeForDensity(UserHandle user, int density) { - return null; - } - - @Override - public Drawable getUserBadgeForDensityNoBackground(UserHandle user, int density) { - return null; - } - - @Override - public CharSequence getUserBadgedLabel(CharSequence label, UserHandle user) { - return null; - } - - @Override - public CharSequence getText(String packageName, int resid, ApplicationInfo appInfo) { - return null; - } - - @Override - public XmlResourceParser getXml(String packageName, int resid, ApplicationInfo appInfo) { - return null; - } - - @Override - public CharSequence getApplicationLabel(ApplicationInfo info) { - return null; - } - - @Override - public Resources getResourcesForActivity(ComponentName activityName) - throws NameNotFoundException { - return null; - } - - @Override - public Resources getResourcesForApplication(ApplicationInfo app) throws NameNotFoundException { - return null; - } - - @Override - public Resources getResourcesForApplication(String appPackageName) - throws NameNotFoundException { - return null; - } - - @Override - public Resources getResourcesForApplicationAsUser(String appPackageName, int userId) - throws NameNotFoundException { - return null; - } - - @Override - public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags, - String installerPackageName) { - } - - @Override - public void installPackage(Uri packageURI, PackageInstallObserver observer, int flags, - String installerPackageName) { - } - - @Override - public int installExistingPackage(String packageName) throws NameNotFoundException { - return 0; - } - - @Override - public int installExistingPackageAsUser(String packageName, int userId) - throws NameNotFoundException { - return 0; - } - - @Override - public void verifyPendingInstall(int id, int verificationCode) { - } - - @Override - public void extendVerificationTimeout(int id, int verificationCodeAtTimeout, - long millisecondsToDelay) { - } - - @Override - public void verifyIntentFilter(int verificationId, int verificationCode, - List<String> outFailedDomains) { - } - - @Override - public int getIntentVerificationStatusAsUser(String packageName, int userId) { - return 0; - } - - @Override - public boolean updateIntentVerificationStatusAsUser(String packageName, int status, int userId) { - return false; - } - - @Override - public List<IntentFilterVerificationInfo> getIntentFilterVerifications(String packageName) { - return null; - } - - @Override - public List<IntentFilter> getAllIntentFilters(String packageName) { - return null; - } - - @Override - public String getDefaultBrowserPackageNameAsUser(int userId) { - return null; - } - - @Override - public boolean setDefaultBrowserPackageNameAsUser(String packageName, int userId) { - return false; - } - - @Override - public void setInstallerPackageName(String targetPackage, String installerPackageName) { - } - - @Override - public void setUpdateAvailable(String packageName, boolean updateAvailable) { - } - - @Override - public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) { - } - - @Override - public void deletePackageAsUser(String packageName, IPackageDeleteObserver observer, int flags, - int userId) { - } - - @Override - public String getInstallerPackageName(String packageName) { - return null; - } - - @Override - public void clearApplicationUserData(String packageName, IPackageDataObserver observer) { - } - - @Override - public void deleteApplicationCacheFiles(String packageName, IPackageDataObserver observer) { - } - - @Override - public void deleteApplicationCacheFilesAsUser(String packageName, int userId, - IPackageDataObserver observer) { - } - - @Override - public void freeStorageAndNotify(String volumeUuid, long freeStorageSize, - IPackageDataObserver observer) { - } - - @Override - public void freeStorage(String volumeUuid, long freeStorageSize, IntentSender pi) { - } - - @Override - public void getPackageSizeInfoAsUser(String packageName, int userHandle, - IPackageStatsObserver observer) { - } - - @Override - public void addPackageToPreferred(String packageName) { - } - - @Override - public void removePackageFromPreferred(String packageName) { - } - - @Override - public List<PackageInfo> getPreferredPackages(int flags) { - return null; - } - - @Override - public void addPreferredActivity(IntentFilter filter, int match, ComponentName[] set, - ComponentName activity) { - } - - @Override - public void replacePreferredActivity(IntentFilter filter, int match, ComponentName[] set, - ComponentName activity) { - } - - @Override - public void clearPackagePreferredActivities(String packageName) { - } - - @Override - public int getPreferredActivities(List<IntentFilter> outFilters, - List<ComponentName> outActivities, String packageName) { - return 0; - } - - @Override - public ComponentName getHomeActivities(List<ResolveInfo> outActivities) { - return null; - } - - @Override - public void setComponentEnabledSetting(ComponentName componentName, int newState, int flags) { - } - - @Override - public int getComponentEnabledSetting(ComponentName componentName) { - return 0; - } - - @Override - public void setApplicationEnabledSetting(String packageName, int newState, int flags) { - } - - @Override - public int getApplicationEnabledSetting(String packageName) { - return 0; - } - - @Override - public void flushPackageRestrictionsAsUser(int userId) { - } - - @Override - public boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden, - UserHandle userHandle) { - return false; - } - - @Override - public boolean getApplicationHiddenSettingAsUser(String packageName, UserHandle userHandle) { - return false; - } - - @Override - public boolean isSafeMode() { - return false; - } - - @Override - public void addOnPermissionsChangeListener(OnPermissionsChangedListener listener) { - } - - @Override - public void removeOnPermissionsChangeListener(OnPermissionsChangedListener listener) { - } - - @Override - public KeySet getKeySetByAlias(String packageName, String alias) { - return null; - } - - @Override - public KeySet getSigningKeySet(String packageName) { - return null; - } - - @Override - public boolean isSignedBy(String packageName, KeySet ks) { - return false; - } - - @Override - public boolean isSignedByExactly(String packageName, KeySet ks) { - return false; - } - - @Override - public String[] setPackagesSuspendedAsUser(String[] packageNames, boolean suspended, - int userId) { - return new String[]{}; - } - - @Override - public boolean isPackageSuspendedForUser(String packageName, int userId) { - return false; - } - - @Override - public void setApplicationCategoryHint(String packageName, int categoryHint) { - } - - @Override - public int getMoveStatus(int moveId) { - return 0; - } - - @Override - public void registerMoveCallback(MoveCallback callback, Handler handler) { - } - - @Override - public void unregisterMoveCallback(MoveCallback callback) { - } - - @Override - public int movePackage(String packageName, VolumeInfo vol) { - return 0; - } - - @Override - public VolumeInfo getPackageCurrentVolume(ApplicationInfo app) { - return null; - } - - @Override - public List<VolumeInfo> getPackageCandidateVolumes(ApplicationInfo app) { - return null; - } - - @Override - public int movePrimaryStorage(VolumeInfo vol) { - return 0; - } - - @Override - public VolumeInfo getPrimaryStorageCurrentVolume() { - return null; - } - - @Override - public List<VolumeInfo> getPrimaryStorageCandidateVolumes() { - return null; - } - - @Override - public VerifierDeviceIdentity getVerifierDeviceIdentity() { - return null; - } - - @Override - public ChangedPackages getChangedPackages(int sequenceNumber) { - return null; - } - - @Override - public boolean isUpgrade() { - return false; - } - - @Override - public PackageInstaller getPackageInstaller() { - return null; - } - - @Override - public void addCrossProfileIntentFilter(IntentFilter filter, int sourceUserId, int targetUserId, - int flags) { - } - - @Override - public void clearCrossProfileIntentFilters(int sourceUserId) { - } - - @Override - public Drawable loadItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo) { - return null; - } - - @Override - public Drawable loadUnbadgedItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo) { - return null; - } - - @Override - public boolean isPackageAvailable(String packageName) { - return false; - } - - @Override - public int getInstallReason(String packageName, UserHandle user) { - return INSTALL_REASON_UNKNOWN; - } - - @Override - public boolean canRequestPackageInstalls() { - return false; - } - - @Override - public ComponentName getInstantAppResolverSettingsComponent() { - return null; - } - - @Override - public ComponentName getInstantAppInstallerComponent() { - return null; - } - - @Override - public String getInstantAppAndroidId(String packageName, UserHandle user) { - return null; - } - - @Override - public void registerDexModule(String dexModulePath, - @Nullable DexModuleRegisterCallback callback) { - callback.onDexModuleRegistered(dexModulePath, false, null); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java deleted file mode 100644 index ed428ec9cfe8..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.android; - -import android.os.IBinder; -import android.os.IPowerManager; -import android.os.PowerManager; -import android.os.PowerSaveState; -import android.os.RemoteException; -import android.os.WorkSource; - -/** - * Fake implementation of IPowerManager. - * - */ -public class BridgePowerManager implements IPowerManager { - - @Override - public boolean isInteractive() throws RemoteException { - return true; - } - - @Override - public boolean isPowerSaveMode() throws RemoteException { - return false; - } - - @Override - public boolean setPowerSaveMode(boolean mode) throws RemoteException { - return false; - } - - public PowerSaveState getPowerSaveState(int serviceType) { - return null; - } - - @Override - public IBinder asBinder() { - // pass for now. - return null; - } - - @Override - public void acquireWakeLock(IBinder arg0, int arg1, String arg2, String arg2_5, WorkSource arg3, String arg4) - throws RemoteException { - // pass for now. - } - - @Override - public void acquireWakeLockWithUid(IBinder arg0, int arg1, String arg2, String arg2_5, int arg3) - throws RemoteException { - // pass for now. - } - - @Override - public void powerHint(int hintId, int data) { - // pass for now. - } - - @Override - public void crash(String arg0) throws RemoteException { - // pass for now. - } - - @Override - public void goToSleep(long arg0, int arg1, int arg2) throws RemoteException { - // pass for now. - } - - @Override - public void nap(long arg0) throws RemoteException { - // pass for now. - } - - @Override - public void reboot(boolean confirm, String reason, boolean wait) { - // pass for now. - } - - @Override - public void rebootSafeMode(boolean confirm, boolean wait) { - // pass for now. - } - - @Override - public void shutdown(boolean confirm, String reason, boolean wait) { - // pass for now. - } - - @Override - public void releaseWakeLock(IBinder arg0, int arg1) throws RemoteException { - // pass for now. - } - - @Override - public void updateWakeLockUids(IBinder arg0, int[] arg1) throws RemoteException { - // pass for now. - } - - @Override - public void setAttentionLight(boolean arg0, int arg1) throws RemoteException { - // pass for now. - } - - @Override - public void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float arg0) throws RemoteException { - // pass for now. - } - - @Override - public void setTemporaryScreenBrightnessSettingOverride(int arg0) throws RemoteException { - // pass for now. - } - - @Override - public void setStayOnSetting(int arg0) throws RemoteException { - // pass for now. - } - - @Override - public void updateWakeLockWorkSource(IBinder arg0, WorkSource arg1, String arg2) throws RemoteException { - // pass for now. - } - - @Override - public boolean isWakeLockLevelSupported(int level) throws RemoteException { - // pass for now. - return true; - } - - @Override - public void userActivity(long time, int event, int flags) throws RemoteException { - // pass for now. - } - - @Override - public void wakeUp(long time, String reason, String opPackageName) throws RemoteException { - // pass for now. - } - - @Override - public void boostScreenBrightness(long time) throws RemoteException { - // pass for now. - } - - @Override - public boolean isDeviceIdleMode() throws RemoteException { - return false; - } - - @Override - public boolean isLightDeviceIdleMode() throws RemoteException { - return false; - } - - @Override - public boolean isScreenBrightnessBoosted() throws RemoteException { - return false; - } - - @Override - public int getLastShutdownReason() { - return PowerManager.SHUTDOWN_REASON_UNKNOWN; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeSharedPreferences.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeSharedPreferences.java deleted file mode 100644 index 132ff2f2e08c..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeSharedPreferences.java +++ /dev/null @@ -1,138 +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 com.android.layoutlib.bridge.android; - -import android.content.SharedPreferences; - -import java.util.Map; -import java.util.Set; - -/** - * An empty shared preferences implementation which doesn't store anything. It always returns - * null, 0 or false. - */ -public class BridgeSharedPreferences implements SharedPreferences { - private Editor mEditor; - - @Override - public Map<String, ?> getAll() { - return null; - } - - @Override - public String getString(String key, String defValue) { - return null; - } - - @Override - public Set<String> getStringSet(String key, Set<String> defValues) { - return null; - } - - @Override - public int getInt(String key, int defValue) { - return 0; - } - - @Override - public long getLong(String key, long defValue) { - return 0; - } - - @Override - public float getFloat(String key, float defValue) { - return 0; - } - - @Override - public boolean getBoolean(String key, boolean defValue) { - return false; - } - - @Override - public boolean contains(String key) { - return false; - } - - @Override - public Editor edit() { - if (mEditor != null) { - return mEditor; - } - mEditor = new Editor() { - @Override - public Editor putString(String key, String value) { - return null; - } - - @Override - public Editor putStringSet(String key, Set<String> values) { - return null; - } - - @Override - public Editor putInt(String key, int value) { - return null; - } - - @Override - public Editor putLong(String key, long value) { - return null; - } - - @Override - public Editor putFloat(String key, float value) { - return null; - } - - @Override - public Editor putBoolean(String key, boolean value) { - return null; - } - - @Override - public Editor remove(String key) { - return null; - } - - @Override - public Editor clear() { - return null; - } - - @Override - public boolean commit() { - return false; - } - - @Override - public void apply() { - } - }; - return mEditor; - } - - @Override - public void registerOnSharedPreferenceChangeListener( - OnSharedPreferenceChangeListener listener) { - } - - @Override - public void unregisterOnSharedPreferenceChangeListener( - OnSharedPreferenceChangeListener listener) { - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java deleted file mode 100644 index ffbe7c43ceab..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.android; - -import com.android.internal.os.IResultReceiver; - -import android.graphics.Rect; -import android.os.Bundle; -import android.os.IBinder; -import android.os.ParcelFileDescriptor; -import android.os.RemoteException; -import android.util.MergedConfiguration; -import android.view.DragEvent; -import android.view.IWindow; - -/** - * Implementation of {@link IWindow} to pass to the AttachInfo. - */ -public final class BridgeWindow implements IWindow { - - @Override - public void dispatchAppVisibility(boolean arg0) throws RemoteException { - // pass for now. - } - - @Override - public void dispatchGetNewSurface() throws RemoteException { - // pass for now. - } - - @Override - public void executeCommand(String arg0, String arg1, ParcelFileDescriptor arg2) - throws RemoteException { - // pass for now. - } - - @Override - public void resized(Rect rect, Rect rect2, Rect rect3, Rect rect4, Rect rect5, Rect rect6, - boolean b, MergedConfiguration mergedConfig, Rect rect7, boolean b2, boolean b3, int i0) - throws RemoteException { - // pass for now. - } - - @Override - public void moved(int arg0, int arg1) throws RemoteException { - // pass for now. - } - - @Override - public void windowFocusChanged(boolean arg0, boolean arg1) throws RemoteException { - // pass for now. - } - - @Override - public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep, - boolean sync) { - // pass for now. - } - - @Override - public void dispatchWallpaperCommand(String action, int x, int y, - int z, Bundle extras, boolean sync) { - // pass for now. - } - - @Override - public void closeSystemDialogs(String reason) { - // pass for now. - } - - @Override - public void dispatchDragEvent(DragEvent event) { - // pass for now. - } - - @Override - public void updatePointerIcon(float x, float y) { - // pass for now - } - - @Override - public void dispatchSystemUiVisibilityChanged(int seq, int globalUi, - int localValue, int localChanges) { - // pass for now. - } - - @Override - public void dispatchWindowShown() { - } - - @Override - public void requestAppKeyboardShortcuts( - IResultReceiver receiver, int deviceId) throws RemoteException { - } - - @Override - public void dispatchPointerCaptureChanged(boolean hasCapture) { - } - - @Override - public IBinder asBinder() { - // pass for now. - return null; - } - -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java deleted file mode 100644 index 2c883940510e..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.android; - -import android.content.ClipData; -import android.graphics.Rect; -import android.graphics.Region; -import android.os.Bundle; -import android.os.IBinder; -import android.os.RemoteException; -import android.util.MergedConfiguration; -import android.view.IWindow; -import android.view.IWindowId; -import android.view.IWindowSession; -import android.view.InputChannel; -import android.view.Surface; -import android.view.SurfaceView; -import android.view.WindowManager.LayoutParams; - -/** - * Implementation of {@link IWindowSession} so that mSession is not null in - * the {@link SurfaceView}. - */ -public final class BridgeWindowSession implements IWindowSession { - - @Override - public int add(IWindow arg0, int seq, LayoutParams arg1, int arg2, Rect arg3, Rect arg4, - InputChannel outInputchannel) - throws RemoteException { - // pass for now. - return 0; - } - - @Override - public int addToDisplay(IWindow arg0, int seq, LayoutParams arg1, int arg2, int displayId, - Rect arg3, Rect arg4, Rect arg5, InputChannel outInputchannel) - throws RemoteException { - // pass for now. - return 0; - } - - @Override - public int addWithoutInputChannel(IWindow arg0, int seq, LayoutParams arg1, int arg2, - Rect arg3, Rect arg4) - throws RemoteException { - // pass for now. - return 0; - } - - @Override - public int addToDisplayWithoutInputChannel(IWindow arg0, int seq, LayoutParams arg1, int arg2, - int displayId, Rect arg3, Rect arg4) - throws RemoteException { - // pass for now. - return 0; - } - - @Override - public void finishDrawing(IWindow arg0) throws RemoteException { - // pass for now. - } - - @Override - public boolean getInTouchMode() throws RemoteException { - // pass for now. - return false; - } - - @Override - public boolean performHapticFeedback(IWindow window, int effectId, boolean always) { - // pass for now. - return false; - } - - @Override - public int relayout(IWindow iWindow, int i, LayoutParams layoutParams, int i2, - int i3, int i4, int i5, Rect rect, Rect rect2, Rect rect3, Rect rect4, Rect rect5, - Rect rect6, Rect rect7, MergedConfiguration mergedConfig, Surface surface) - throws RemoteException { - // pass for now. - return 0; - } - - @Override - public boolean outOfMemory(IWindow window) throws RemoteException { - return false; - } - - @Override - public void getDisplayFrame(IWindow window, Rect outDisplayFrame) { - // pass for now. - } - - @Override - public void remove(IWindow arg0) throws RemoteException { - // pass for now. - } - - @Override - public void setInTouchMode(boolean arg0) throws RemoteException { - // pass for now. - } - - @Override - public void setTransparentRegion(IWindow arg0, Region arg1) throws RemoteException { - // pass for now. - } - - @Override - public void setInsets(IWindow window, int touchable, Rect contentInsets, - Rect visibleInsets, Region touchableRegion) { - // pass for now. - } - - @Override - public IBinder prepareDrag(IWindow window, int flags, - int thumbnailWidth, int thumbnailHeight, Surface outSurface) - throws RemoteException { - // pass for now - return null; - } - - @Override - public boolean performDrag(IWindow window, IBinder dragToken, - int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY, - ClipData data) - throws RemoteException { - // pass for now - return false; - } - - @Override - public boolean startMovingTask(IWindow window, float startX, float startY) - throws RemoteException { - // pass for now - return false; - } - - @Override - public void reportDropResult(IWindow window, boolean consumed) throws RemoteException { - // pass for now - } - - @Override - public void cancelDragAndDrop(IBinder dragToken) throws RemoteException { - // pass for now - } - - @Override - public void dragRecipientEntered(IWindow window) throws RemoteException { - // pass for now - } - - @Override - public void dragRecipientExited(IWindow window) throws RemoteException { - // pass for now - } - - @Override - public void setWallpaperPosition(IBinder window, float x, float y, - float xStep, float yStep) { - // pass for now. - } - - @Override - public void wallpaperOffsetsComplete(IBinder window) { - // pass for now. - } - - @Override - public void setWallpaperDisplayOffset(IBinder windowToken, int x, int y) { - // pass for now. - } - - @Override - public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y, - int z, Bundle extras, boolean sync) { - // pass for now. - return null; - } - - @Override - public void wallpaperCommandComplete(IBinder window, Bundle result) { - // pass for now. - } - - @Override - public IBinder asBinder() { - // pass for now. - return null; - } - - @Override - public void onRectangleOnScreenRequested(IBinder window, Rect rectangle) { - // pass for now. - } - - @Override - public IWindowId getWindowId(IBinder window) throws RemoteException { - // pass for now. - return null; - } - - @Override - public void pokeDrawLock(IBinder window) { - // pass for now. - } - - @Override - public void prepareToReplaceWindows(IBinder appToken, boolean childrenOnly) { - // pass for now. - } - - @Override - public void updatePointerIcon(IWindow window) { - // pass for now. - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java deleted file mode 100644 index ac8712eaa025..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java +++ /dev/null @@ -1,494 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.android; - - -import com.android.ide.common.rendering.api.ILayoutPullParser; -import com.android.layoutlib.bridge.impl.ParserFactory; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import android.content.res.XmlResourceParser; -import android.util.AttributeSet; -import android.util.BridgeXmlPullAttributes; - -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; - -/** - * {@link BridgeXmlBlockParser} reimplements most of android.xml.XmlBlock.Parser. - * It delegates to both an instance of {@link XmlPullParser} and an instance of - * XmlPullAttributes (for the {@link AttributeSet} part). - */ -public class BridgeXmlBlockParser implements XmlResourceParser { - - private final XmlPullParser mParser; - private final BridgeXmlPullAttributes mAttrib; - private final BridgeContext mContext; - private final boolean mPlatformFile; - - private boolean mStarted = false; - private int mEventType = START_DOCUMENT; - - private boolean mPopped = true; // default to true in case it's not pushed. - - /** - * Builds a {@link BridgeXmlBlockParser}. - * @param parser The XmlPullParser to get the content from. - * @param context the Context. - * @param platformFile Indicates whether the the file is a platform file or not. - */ - public BridgeXmlBlockParser(XmlPullParser parser, BridgeContext context, boolean platformFile) { - if (ParserFactory.LOG_PARSER) { - System.out.println("CRTE " + parser.toString()); - } - - mParser = parser; - mContext = context; - mPlatformFile = platformFile; - mAttrib = new BridgeXmlPullAttributes(parser, context, mPlatformFile); - - if (mContext != null) { - mContext.pushParser(this); - mPopped = false; - } - } - - public XmlPullParser getParser() { - return mParser; - } - - public boolean isPlatformFile() { - return mPlatformFile; - } - - public Object getViewCookie() { - if (mParser instanceof ILayoutPullParser) { - return ((ILayoutPullParser)mParser).getViewCookie(); - } - - return null; - } - - public void ensurePopped() { - if (mContext != null && mPopped == false) { - mContext.popParser(); - mPopped = true; - } - } - - // ------- XmlResourceParser implementation - - @Override - public void setFeature(String name, boolean state) - throws XmlPullParserException { - if (FEATURE_PROCESS_NAMESPACES.equals(name) && state) { - return; - } - if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name) && state) { - return; - } - throw new XmlPullParserException("Unsupported feature: " + name); - } - - @Override - public boolean getFeature(String name) { - if (FEATURE_PROCESS_NAMESPACES.equals(name)) { - return true; - } - if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name)) { - return true; - } - return false; - } - - @Override - public void setProperty(String name, Object value) throws XmlPullParserException { - throw new XmlPullParserException("setProperty() not supported"); - } - - @Override - public Object getProperty(String name) { - return null; - } - - @Override - public void setInput(Reader in) throws XmlPullParserException { - mParser.setInput(in); - } - - @Override - public void setInput(InputStream inputStream, String inputEncoding) - throws XmlPullParserException { - mParser.setInput(inputStream, inputEncoding); - } - - @Override - public void defineEntityReplacementText(String entityName, - String replacementText) throws XmlPullParserException { - throw new XmlPullParserException( - "defineEntityReplacementText() not supported"); - } - - @Override - public String getNamespacePrefix(int pos) throws XmlPullParserException { - throw new XmlPullParserException("getNamespacePrefix() not supported"); - } - - @Override - public String getInputEncoding() { - return null; - } - - @Override - public String getNamespace(String prefix) { - throw new RuntimeException("getNamespace() not supported"); - } - - @Override - public int getNamespaceCount(int depth) throws XmlPullParserException { - throw new XmlPullParserException("getNamespaceCount() not supported"); - } - - @Override - public String getPositionDescription() { - return "Binary XML file line #" + getLineNumber(); - } - - @Override - public String getNamespaceUri(int pos) throws XmlPullParserException { - throw new XmlPullParserException("getNamespaceUri() not supported"); - } - - @Override - public int getColumnNumber() { - return -1; - } - - @Override - public int getDepth() { - return mParser.getDepth(); - } - - @Override - public String getText() { - return mParser.getText(); - } - - @Override - public int getLineNumber() { - return mParser.getLineNumber(); - } - - @Override - public int getEventType() { - return mEventType; - } - - @Override - public boolean isWhitespace() throws XmlPullParserException { - // Original comment: whitespace was stripped by aapt. - return mParser.isWhitespace(); - } - - @Override - public String getPrefix() { - throw new RuntimeException("getPrefix not supported"); - } - - @Override - public char[] getTextCharacters(int[] holderForStartAndLength) { - String txt = getText(); - char[] chars = null; - if (txt != null) { - holderForStartAndLength[0] = 0; - holderForStartAndLength[1] = txt.length(); - chars = new char[txt.length()]; - txt.getChars(0, txt.length(), chars, 0); - } - return chars; - } - - @Override - public String getNamespace() { - return mParser.getNamespace(); - } - - @Override - public String getName() { - return mParser.getName(); - } - - @Override - public String getAttributeNamespace(int index) { - return mParser.getAttributeNamespace(index); - } - - @Override - public String getAttributeName(int index) { - return mParser.getAttributeName(index); - } - - @Override - public String getAttributePrefix(int index) { - throw new RuntimeException("getAttributePrefix not supported"); - } - - @Override - public boolean isEmptyElementTag() { - // XXX Need to detect this. - return false; - } - - @Override - public int getAttributeCount() { - return mParser.getAttributeCount(); - } - - @Override - public String getAttributeValue(int index) { - return mParser.getAttributeValue(index); - } - - @Override - public String getAttributeType(int index) { - return "CDATA"; - } - - @Override - public boolean isAttributeDefault(int index) { - return false; - } - - @Override - public int nextToken() throws XmlPullParserException, IOException { - return next(); - } - - @Override - public String getAttributeValue(String namespace, String name) { - return mParser.getAttributeValue(namespace, name); - } - - @Override - public int next() throws XmlPullParserException, IOException { - if (!mStarted) { - mStarted = true; - - if (ParserFactory.LOG_PARSER) { - System.out.println("STRT " + mParser.toString()); - } - - return START_DOCUMENT; - } - - int ev = mParser.next(); - - if (ParserFactory.LOG_PARSER) { - System.out.println("NEXT " + mParser.toString() + " " + - eventTypeToString(mEventType) + " -> " + eventTypeToString(ev)); - } - - if (ev == END_TAG && mParser.getDepth() == 1) { - // done with parser remove it from the context stack. - ensurePopped(); - - if (ParserFactory.LOG_PARSER) { - System.out.println(""); - } - } - - mEventType = ev; - return ev; - } - - public static String eventTypeToString(int eventType) { - switch (eventType) { - case START_DOCUMENT: - return "START_DOC"; - case END_DOCUMENT: - return "END_DOC"; - case START_TAG: - return "START_TAG"; - case END_TAG: - return "END_TAG"; - case TEXT: - return "TEXT"; - case CDSECT: - return "CDSECT"; - case ENTITY_REF: - return "ENTITY_REF"; - case IGNORABLE_WHITESPACE: - return "IGNORABLE_WHITESPACE"; - case PROCESSING_INSTRUCTION: - return "PROCESSING_INSTRUCTION"; - case COMMENT: - return "COMMENT"; - case DOCDECL: - return "DOCDECL"; - } - - return "????"; - } - - @Override - public void require(int type, String namespace, String name) - throws XmlPullParserException { - if (type != getEventType() - || (namespace != null && !namespace.equals(getNamespace())) - || (name != null && !name.equals(getName()))) - throw new XmlPullParserException("expected " + TYPES[type] - + getPositionDescription()); - } - - @Override - public String nextText() throws XmlPullParserException, IOException { - if (getEventType() != START_TAG) { - throw new XmlPullParserException(getPositionDescription() - + ": parser must be on START_TAG to read next text", this, - null); - } - int eventType = next(); - if (eventType == TEXT) { - String result = getText(); - eventType = next(); - if (eventType != END_TAG) { - throw new XmlPullParserException( - getPositionDescription() - + ": event TEXT it must be immediately followed by END_TAG", - this, null); - } - return result; - } else if (eventType == END_TAG) { - return ""; - } else { - throw new XmlPullParserException(getPositionDescription() - + ": parser must be on START_TAG or TEXT to read text", - this, null); - } - } - - @Override - public int nextTag() throws XmlPullParserException, IOException { - int eventType = next(); - if (eventType == TEXT && isWhitespace()) { // skip whitespace - eventType = next(); - } - if (eventType != START_TAG && eventType != END_TAG) { - throw new XmlPullParserException(getPositionDescription() - + ": expected start or end tag", this, null); - } - return eventType; - } - - // AttributeSet implementation - - - @Override - public void close() { - // pass - } - - @Override - public boolean getAttributeBooleanValue(int index, boolean defaultValue) { - return mAttrib.getAttributeBooleanValue(index, defaultValue); - } - - @Override - public boolean getAttributeBooleanValue(String namespace, String attribute, - boolean defaultValue) { - return mAttrib.getAttributeBooleanValue(namespace, attribute, defaultValue); - } - - @Override - public float getAttributeFloatValue(int index, float defaultValue) { - return mAttrib.getAttributeFloatValue(index, defaultValue); - } - - @Override - public float getAttributeFloatValue(String namespace, String attribute, float defaultValue) { - return mAttrib.getAttributeFloatValue(namespace, attribute, defaultValue); - } - - @Override - public int getAttributeIntValue(int index, int defaultValue) { - return mAttrib.getAttributeIntValue(index, defaultValue); - } - - @Override - public int getAttributeIntValue(String namespace, String attribute, int defaultValue) { - return mAttrib.getAttributeIntValue(namespace, attribute, defaultValue); - } - - @Override - public int getAttributeListValue(int index, String[] options, int defaultValue) { - return mAttrib.getAttributeListValue(index, options, defaultValue); - } - - @Override - public int getAttributeListValue(String namespace, String attribute, - String[] options, int defaultValue) { - return mAttrib.getAttributeListValue(namespace, attribute, options, defaultValue); - } - - @Override - public int getAttributeNameResource(int index) { - return mAttrib.getAttributeNameResource(index); - } - - @Override - public int getAttributeResourceValue(int index, int defaultValue) { - return mAttrib.getAttributeResourceValue(index, defaultValue); - } - - @Override - public int getAttributeResourceValue(String namespace, String attribute, int defaultValue) { - return mAttrib.getAttributeResourceValue(namespace, attribute, defaultValue); - } - - @Override - public int getAttributeUnsignedIntValue(int index, int defaultValue) { - return mAttrib.getAttributeUnsignedIntValue(index, defaultValue); - } - - @Override - public int getAttributeUnsignedIntValue(String namespace, String attribute, int defaultValue) { - return mAttrib.getAttributeUnsignedIntValue(namespace, attribute, defaultValue); - } - - @Override - public String getClassAttribute() { - return mAttrib.getClassAttribute(); - } - - @Override - public String getIdAttribute() { - return mAttrib.getIdAttribute(); - } - - @Override - public int getIdAttributeResourceValue(int defaultValue) { - return mAttrib.getIdAttributeResourceValue(defaultValue); - } - - @Override - public int getStyleAttribute() { - return mAttrib.getStyleAttribute(); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java deleted file mode 100644 index 051de9055042..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java +++ /dev/null @@ -1,65 +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 com.android.layoutlib.bridge.android; - -import com.android.ide.common.rendering.api.LayoutlibCallback; -import com.android.ide.common.rendering.api.RenderParams; -import com.android.ide.common.rendering.api.SessionParams.Key; - -/** - * This contains all known keys for the {@link RenderParams#getFlag(Key)}. - * <p/> - * The IDE has its own copy of this class which may be newer or older than this one. - * <p/> - * Constants should never be modified or removed from this class. - */ -public final class RenderParamsFlags { - - public static final Key<String> FLAG_KEY_ROOT_TAG = - new Key<String>("rootTag", String.class); - public static final Key<Boolean> FLAG_KEY_DISABLE_BITMAP_CACHING = - new Key<Boolean>("disableBitmapCaching", Boolean.class); - public static final Key<Boolean> FLAG_KEY_RENDER_ALL_DRAWABLE_STATES = - new Key<Boolean>("renderAllDrawableStates", Boolean.class); - /** - * To tell LayoutLib that the IDE supports RecyclerView. - * <p/> - * Default is false. - */ - public static final Key<Boolean> FLAG_KEY_RECYCLER_VIEW_SUPPORT = - new Key<Boolean>("recyclerViewSupport", Boolean.class); - /** - * The application package name. Used via {@link LayoutlibCallback#getFlag(Key)} - */ - public static final Key<String> FLAG_KEY_APPLICATION_PACKAGE = - new Key<String>("applicationPackage", String.class); - /** - * To tell LayoutLib that IDE supports providing XML Parser for a file (useful for getting in - * memory contents of the file). Used via {@link LayoutlibCallback#getFlag(Key)} - */ - public static final Key<Boolean> FLAG_KEY_XML_FILE_PARSER_SUPPORT = - new Key<Boolean>("xmlFileParser", Boolean.class); - /** - * To tell LayoutLib to not render when creating a new session. This allows controlling when the first - * layout rendering will happen. - */ - public static final Key<Boolean> FLAG_DO_NOT_RENDER_ON_CREATE = - new Key<Boolean>("doNotRenderOnCreate", Boolean.class); - - // Disallow instances. - private RenderParamsFlags() {} -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/graphics/NopCanvas.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/graphics/NopCanvas.java deleted file mode 100644 index 131aa1752ba0..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/graphics/NopCanvas.java +++ /dev/null @@ -1,307 +0,0 @@ -/* - * 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 com.android.layoutlib.bridge.android.graphics; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.graphics.NinePatch; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.Picture; -import android.graphics.PorterDuff.Mode; -import android.graphics.Rect; -import android.graphics.RectF; - -/** - * Canvas implementation that does not do any rendering - */ -public class NopCanvas extends Canvas { - private boolean mIsInitialized = false; - - public NopCanvas() { - super(); - mIsInitialized = true; - } - - @Override - public boolean isHardwareAccelerated() { - // We return true the first time so there are no allocations for the software renderer in - // the constructor - return !mIsInitialized; - } - - @Override - public int save() { - return 0; - } - - @Override - public int save(int saveFlags) { - return 0; - } - - @Override - public int saveLayer(RectF bounds, Paint paint, int saveFlags) { - return 0; - } - - @Override - public int saveLayer(RectF bounds, Paint paint) { - return 0; - } - - @Override - public int saveLayer(float left, float top, float right, float bottom, Paint paint, - int saveFlags) { - return 0; - } - - @Override - public int saveLayer(float left, float top, float right, float bottom, Paint paint) { - return 0; - } - - @Override - public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) { - return 0; - } - - @Override - public int saveLayerAlpha(RectF bounds, int alpha) { - return 0; - } - - @Override - public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha, - int saveFlags) { - return 0; - } - - @Override - public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha) { - return 0; - } - - @Override - public void restore() { - } - - @Override - public int getSaveCount() { - return 0; - } - - @Override - public void restoreToCount(int saveCount) { - } - - @Override - public void drawRGB(int r, int g, int b) { - } - - @Override - public void drawARGB(int a, int r, int g, int b) { - } - - @Override - public void drawColor(int color) { - } - - @Override - public void drawColor(int color, Mode mode) { - } - - @Override - public void drawPaint(Paint paint) { - } - - @Override - public void drawPoints(float[] pts, int offset, int count, Paint paint) { - } - - @Override - public void drawPoints(float[] pts, Paint paint) { - } - - @Override - public void drawPoint(float x, float y, Paint paint) { - } - - @Override - public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) { - } - - @Override - public void drawLines(float[] pts, int offset, int count, Paint paint) { - } - - @Override - public void drawLines(float[] pts, Paint paint) { - } - - @Override - public void drawRect(RectF rect, Paint paint) { - } - - @Override - public void drawRect(Rect r, Paint paint) { - } - - @Override - public void drawRect(float left, float top, float right, float bottom, Paint paint) { - } - - @Override - public void drawOval(RectF oval, Paint paint) { - } - - @Override - public void drawOval(float left, float top, float right, float bottom, Paint paint) { - } - - @Override - public void drawCircle(float cx, float cy, float radius, Paint paint) { - } - - @Override - public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, - Paint paint) { - } - - @Override - public void drawArc(float left, float top, float right, float bottom, float startAngle, - float sweepAngle, boolean useCenter, Paint paint) { - } - - @Override - public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) { - } - - @Override - public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, - Paint paint) { - } - - @Override - public void drawPath(Path path, Paint paint) { - } - - @Override - protected void throwIfCannotDraw(Bitmap bitmap) { - } - - @Override - public void drawPatch(NinePatch patch, Rect dst, Paint paint) { - } - - @Override - public void drawPatch(NinePatch patch, RectF dst, Paint paint) { - } - - @Override - public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) { - } - - @Override - public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) { - } - - @Override - public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) { - } - - @Override - public void drawBitmap(int[] colors, int offset, int stride, float x, float y, int width, - int height, boolean hasAlpha, Paint paint) { - } - - @Override - public void drawBitmap(int[] colors, int offset, int stride, int x, int y, int width, - int height, boolean hasAlpha, Paint paint) { - } - - @Override - public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) { - } - - @Override - public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts, - int vertOffset, int[] colors, int colorOffset, Paint paint) { - } - - @Override - public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset, - float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices, - int indexOffset, int indexCount, Paint paint) { - } - - @Override - public void drawText(char[] text, int index, int count, float x, float y, Paint paint) { - } - - @Override - public void drawText(String text, float x, float y, Paint paint) { - } - - @Override - public void drawText(String text, int start, int end, float x, float y, Paint paint) { - } - - @Override - public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) { - } - - @Override - public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount, - float x, float y, boolean isRtl, Paint paint) { - } - - @Override - public void drawTextRun(CharSequence text, int start, int end, int contextStart, int contextEnd, - float x, float y, boolean isRtl, Paint paint) { - } - - @Override - public void drawPosText(char[] text, int index, int count, float[] pos, Paint paint) { - } - - @Override - public void drawPosText(String text, float[] pos, Paint paint) { - } - - @Override - public void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset, - float vOffset, Paint paint) { - } - - @Override - public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) { - } - - @Override - public void drawPicture(Picture picture) { - } - - @Override - public void drawPicture(Picture picture, RectF dst) { - } - - @Override - public void drawPicture(Picture picture, Rect dst) { - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/DesignLibUtil.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/DesignLibUtil.java deleted file mode 100644 index aa873a6476ae..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/DesignLibUtil.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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 com.android.layoutlib.bridge.android.support; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.util.ReflectionUtils.ReflectionException; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.view.View; - -import static com.android.layoutlib.bridge.util.ReflectionUtils.getMethod; -import static com.android.layoutlib.bridge.util.ReflectionUtils.invoke; - -/** - * Utility class for working with the design support lib. - */ -public class DesignLibUtil { - - private static final String PKG_PREFIX = "android.support.design.widget."; - public static final String CN_COORDINATOR_LAYOUT = PKG_PREFIX + "CoordinatorLayout"; - public static final String CN_APPBAR_LAYOUT = PKG_PREFIX + "AppBarLayout"; - public static final String CN_COLLAPSING_TOOLBAR_LAYOUT = - PKG_PREFIX + "CollapsingToolbarLayout"; - public static final String CN_TOOLBAR = "android.support.v7.widget.Toolbar"; - public static final int SCROLL_AXIS_VERTICAL = 1 << 1; - - /** - * Tries to set the title of a view. This is used to set the title in a - * CollapsingToolbarLayout. - * <p/> - * Any exceptions thrown during the process are logged in {@link Bridge#getLog()} - */ - public static void setTitle(@NonNull View view, @Nullable String title) { - if (title == null) { - return; - } - try { - invoke(getMethod(view.getClass(), "setTitle", CharSequence.class), view, title); - } catch (ReflectionException e) { - Bridge.getLog().warning(LayoutLog.TAG_INFO, - "Error occurred while trying to set title.", e); - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/DrawerLayoutUtil.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/DrawerLayoutUtil.java deleted file mode 100644 index 40d3811cbdf7..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/DrawerLayoutUtil.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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 com.android.layoutlib.bridge.android.support; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.util.ReflectionUtils.ReflectionException; - -import android.annotation.Nullable; -import android.view.View; - -import static android.view.Gravity.END; -import static android.view.Gravity.LEFT; -import static android.view.Gravity.RIGHT; -import static android.view.Gravity.START; -import static com.android.layoutlib.bridge.util.ReflectionUtils.getCause; -import static com.android.layoutlib.bridge.util.ReflectionUtils.getMethod; -import static com.android.layoutlib.bridge.util.ReflectionUtils.invoke; - -public class DrawerLayoutUtil { - - public static final String CN_DRAWER_LAYOUT = "android.support.v4.widget.DrawerLayout"; - - public static void openDrawer(View drawerLayout, @Nullable String drawerGravity) { - int gravity = -1; - if ("left".equals(drawerGravity)) { - gravity = LEFT; - } else if ("right".equals(drawerGravity)) { - gravity = RIGHT; - } else if ("start".equals(drawerGravity)) { - gravity = START; - } else if ("end".equals(drawerGravity)) { - gravity = END; - } - if (gravity > 0) { - openDrawer(drawerLayout, gravity); - } - } - - private static void openDrawer(View drawerLayout, int gravity) { - try { - invoke(getMethod(drawerLayout.getClass(), "openDrawer", int.class), drawerLayout, - gravity); - } catch (ReflectionException e) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, "Unable to open navigation drawer", - getCause(e), null); - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java deleted file mode 100644 index ab278195f328..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * 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 com.android.layoutlib.bridge.android.support; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.ide.common.rendering.api.LayoutlibCallback; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.android.RenderParamsFlags; -import com.android.layoutlib.bridge.util.ReflectionUtils; -import com.android.layoutlib.bridge.util.ReflectionUtils.ReflectionException; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.view.View; - -import static com.android.layoutlib.bridge.util.ReflectionUtils.getCause; -import static com.android.layoutlib.bridge.util.ReflectionUtils.getMethod; -import static com.android.layoutlib.bridge.util.ReflectionUtils.invoke; - -/** - * Utility class for working with android.support.v7.widget.RecyclerView - */ -public class RecyclerViewUtil { - - private static final String RV_PKG_PREFIX = "android.support.v7.widget."; - public static final String CN_RECYCLER_VIEW = RV_PKG_PREFIX + "RecyclerView"; - private static final String CN_LAYOUT_MANAGER = CN_RECYCLER_VIEW + "$LayoutManager"; - private static final String CN_ADAPTER = CN_RECYCLER_VIEW + "$Adapter"; - - // LinearLayoutManager related constants. - private static final String CN_LINEAR_LAYOUT_MANAGER = RV_PKG_PREFIX + "LinearLayoutManager"; - private static final Class<?>[] LLM_CONSTRUCTOR_SIGNATURE = new Class<?>[]{Context.class}; - - /** - * Tries to create an Adapter ({@code android.support.v7.widget.RecyclerView.Adapter} and a - * LayoutManager {@code RecyclerView.LayoutManager} and assign these to the {@code RecyclerView} - * that is passed. - * <p/> - * Any exceptions thrown during the process are logged in {@link Bridge#getLog()} - */ - public static void setAdapter(@NonNull View recyclerView, @NonNull BridgeContext context, - @NonNull LayoutlibCallback layoutlibCallback, int adapterLayout) { - try { - setLayoutManager(recyclerView, context, layoutlibCallback); - Object adapter = createAdapter(layoutlibCallback); - if (adapter != null) { - setProperty(recyclerView, CN_ADAPTER, adapter, "setAdapter"); - setProperty(adapter, int.class, adapterLayout, "setLayoutId"); - } - } catch (ReflectionException e) { - Throwable cause = getCause(e); - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "Error occurred while trying to setup RecyclerView.", cause, null); - } - } - - private static void setLayoutManager(@NonNull View recyclerView, @NonNull BridgeContext context, - @NonNull LayoutlibCallback callback) throws ReflectionException { - if (getLayoutManager(recyclerView) == null) { - // Only set the layout manager if not already set by the recycler view. - Object layoutManager = createLayoutManager(context, callback); - if (layoutManager != null) { - setProperty(recyclerView, CN_LAYOUT_MANAGER, layoutManager, "setLayoutManager"); - } - } - } - - /** Creates a LinearLayoutManager using the provided context. */ - @Nullable - private static Object createLayoutManager(@NonNull Context context, - @NonNull LayoutlibCallback callback) - throws ReflectionException { - try { - return callback.loadView(CN_LINEAR_LAYOUT_MANAGER, LLM_CONSTRUCTOR_SIGNATURE, - new Object[]{context}); - } catch (Exception e) { - throw new ReflectionException(e); - } - } - - @Nullable - private static Object getLayoutManager(View recyclerView) throws ReflectionException { - return invoke(getMethod(recyclerView.getClass(), "getLayoutManager"), recyclerView); - } - - @Nullable - private static Object createAdapter(@NonNull LayoutlibCallback layoutlibCallback) - throws ReflectionException { - Boolean ideSupport = - layoutlibCallback.getFlag(RenderParamsFlags.FLAG_KEY_RECYCLER_VIEW_SUPPORT); - if (ideSupport != Boolean.TRUE) { - return null; - } - try { - return layoutlibCallback.loadClass(CN_ADAPTER, new Class[0], new Object[0]); - } catch (Exception e) { - throw new ReflectionException(e); - } - } - - private static void setProperty(@NonNull Object object, @NonNull String propertyClassName, - @NonNull Object propertyValue, @NonNull String propertySetter) - throws ReflectionException { - Class<?> propertyClass = ReflectionUtils.getClassInstance(propertyValue, propertyClassName); - setProperty(object, propertyClass, propertyValue, propertySetter); - } - - private static void setProperty(@NonNull Object object, @NonNull Class<?> propertyClass, - @Nullable Object propertyValue, @NonNull String propertySetter) - throws ReflectionException { - invoke(getMethod(object.getClass(), propertySetter, propertyClass), object, propertyValue); - } - -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/SupportPreferencesUtil.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/SupportPreferencesUtil.java deleted file mode 100644 index 6ad9efc81afa..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/SupportPreferencesUtil.java +++ /dev/null @@ -1,282 +0,0 @@ -/* - * 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 com.android.layoutlib.bridge.android.support; - -import com.android.ide.common.rendering.api.LayoutlibCallback; -import com.android.ide.common.rendering.api.RenderResources; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.rendering.api.StyleResourceValue; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; -import com.android.layoutlib.bridge.util.ReflectionUtils.ReflectionException; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.view.ContextThemeWrapper; -import android.view.View; -import android.view.ViewGroup; -import android.widget.LinearLayout; -import android.widget.LinearLayout.LayoutParams; -import android.widget.ScrollView; - -import java.io.IOException; -import java.lang.reflect.Method; -import java.util.ArrayList; - -import static com.android.layoutlib.bridge.util.ReflectionUtils.getAccessibleMethod; -import static com.android.layoutlib.bridge.util.ReflectionUtils.getClassInstance; -import static com.android.layoutlib.bridge.util.ReflectionUtils.getMethod; -import static com.android.layoutlib.bridge.util.ReflectionUtils.invoke; - -/** - * Class with utility methods to instantiate Preferences provided by the support library. - * This class uses reflection to access the support preference objects so it heavily depends on - * the API being stable. - */ -public class SupportPreferencesUtil { - private static final String PREFERENCE_PKG = "android.support.v7.preference"; - private static final String PREFERENCE_MANAGER = PREFERENCE_PKG + ".PreferenceManager"; - private static final String PREFERENCE_GROUP = PREFERENCE_PKG + ".PreferenceGroup"; - private static final String PREFERENCE_GROUP_ADAPTER = - PREFERENCE_PKG + ".PreferenceGroupAdapter"; - private static final String PREFERENCE_INFLATER = PREFERENCE_PKG + ".PreferenceInflater"; - - private SupportPreferencesUtil() { - } - - @NonNull - private static Object instantiateClass(@NonNull LayoutlibCallback callback, - @NonNull String className, @Nullable Class[] constructorSignature, - @Nullable Object[] constructorArgs) throws ReflectionException { - try { - Object instance = callback.loadClass(className, constructorSignature, constructorArgs); - if (instance == null) { - throw new ClassNotFoundException(className + " class not found"); - } - return instance; - } catch (ClassNotFoundException e) { - throw new ReflectionException(e); - } - } - - @NonNull - private static Object createPreferenceGroupAdapter(@NonNull LayoutlibCallback callback, - @NonNull Object preferenceScreen) throws ReflectionException { - Class<?> preferenceGroupClass = getClassInstance(preferenceScreen, PREFERENCE_GROUP); - - return instantiateClass(callback, PREFERENCE_GROUP_ADAPTER, - new Class[]{preferenceGroupClass}, new Object[]{preferenceScreen}); - } - - @NonNull - private static Object createInflatedPreference(@NonNull LayoutlibCallback callback, - @NonNull Context context, @NonNull XmlPullParser parser, @NonNull Object preferenceScreen, - @NonNull Object preferenceManager) throws ReflectionException { - Class<?> preferenceGroupClass = getClassInstance(preferenceScreen, PREFERENCE_GROUP); - Object preferenceInflater = instantiateClass(callback, PREFERENCE_INFLATER, - new Class[]{Context.class, preferenceManager.getClass()}, - new Object[]{context, preferenceManager}); - Object inflatedPreference = - invoke(getAccessibleMethod(preferenceInflater.getClass(), "inflate", - XmlPullParser.class, preferenceGroupClass), preferenceInflater, parser, - null); - - if (inflatedPreference == null) { - throw new ReflectionException("inflate method returned null"); - } - - return inflatedPreference; - } - - /** - * Returns a themed wrapper context of {@link BridgeContext} with the theme specified in - * ?attr/preferenceTheme applied to it. - */ - @Nullable - private static Context getThemedContext(@NonNull BridgeContext bridgeContext) { - RenderResources resources = bridgeContext.getRenderResources(); - ResourceValue preferenceTheme = resources.findItemInTheme("preferenceTheme", false); - - if (preferenceTheme != null) { - // resolve it, if needed. - preferenceTheme = resources.resolveResValue(preferenceTheme); - } - if (preferenceTheme instanceof StyleResourceValue) { - int styleId = bridgeContext.getDynamicIdByStyle(((StyleResourceValue) preferenceTheme)); - if (styleId != 0) { - return new ContextThemeWrapper(bridgeContext, styleId); - } - } - - return null; - } - - /** - * Returns a {@link LinearLayout} containing all the UI widgets representing the preferences - * passed in the group adapter. - */ - @Nullable - private static LinearLayout setUpPreferencesListView(@NonNull BridgeContext bridgeContext, - @NonNull Context themedContext, @NonNull ArrayList<Object> viewCookie, - @NonNull Object preferenceGroupAdapter) throws ReflectionException { - // Setup the LinearLayout that will contain the preferences - LinearLayout listView = new LinearLayout(themedContext); - listView.setOrientation(LinearLayout.VERTICAL); - listView.setLayoutParams( - new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); - - if (!viewCookie.isEmpty()) { - bridgeContext.addViewKey(listView, viewCookie.get(0)); - } - - // Get all the preferences and add them to the LinearLayout - Integer preferencesCount = - (Integer) invoke(getMethod(preferenceGroupAdapter.getClass(), "getItemCount"), - preferenceGroupAdapter); - if (preferencesCount == null) { - return listView; - } - - Method getItemId = getMethod(preferenceGroupAdapter.getClass(), "getItemId", int.class); - Method getItemViewType = - getMethod(preferenceGroupAdapter.getClass(), "getItemViewType", int.class); - Method onCreateViewHolder = - getMethod(preferenceGroupAdapter.getClass(), "onCreateViewHolder", ViewGroup.class, - int.class); - for (int i = 0; i < preferencesCount; i++) { - Long id = (Long) invoke(getItemId, preferenceGroupAdapter, i); - if (id == null) { - continue; - } - - // Get the type of the preference layout and bind it to a newly created view holder - Integer type = (Integer) invoke(getItemViewType, preferenceGroupAdapter, i); - Object viewHolder = - invoke(onCreateViewHolder, preferenceGroupAdapter, listView, type); - if (viewHolder == null) { - continue; - } - invoke(getMethod(preferenceGroupAdapter.getClass(), "onBindViewHolder", - viewHolder.getClass(), int.class), preferenceGroupAdapter, viewHolder, i); - - try { - // Get the view from the view holder and add it to our layout - View itemView = - (View) viewHolder.getClass().getField("itemView").get(viewHolder); - - int arrayPosition = id.intValue() - 1; // IDs are 1 based - if (arrayPosition >= 0 && arrayPosition < viewCookie.size()) { - bridgeContext.addViewKey(itemView, viewCookie.get(arrayPosition)); - } - listView.addView(itemView); - } catch (IllegalAccessException | NoSuchFieldException ignored) { - } - } - - return listView; - } - - /** - * Inflates a preferences layout using the support library. If the support library is not - * available, this method will return null without advancing the parsers. - */ - @Nullable - public static View inflatePreference(@NonNull BridgeContext bridgeContext, - @NonNull XmlPullParser parser, @Nullable ViewGroup root) { - try { - LayoutlibCallback callback = bridgeContext.getLayoutlibCallback(); - - Context context = getThemedContext(bridgeContext); - if (context == null) { - // Probably we couldn't find the "preferenceTheme" in the theme - return null; - } - - // Create PreferenceManager - Object preferenceManager = - instantiateClass(callback, PREFERENCE_MANAGER, new Class[]{Context.class}, - new Object[]{context}); - - // From this moment on, we can assume that we found the support library and that - // nothing should fail - - // Create PreferenceScreen - Object preferenceScreen = - invoke(getMethod(preferenceManager.getClass(), "createPreferenceScreen", - Context.class), preferenceManager, context); - if (preferenceScreen == null) { - return null; - } - - // Setup a parser that stores the list of cookies in the same order as the preferences - // are inflated. That way we can later reconstruct the list using the preference id - // since they are sequential and start in 1. - ArrayList<Object> viewCookie = new ArrayList<>(); - if (parser instanceof BridgeXmlBlockParser) { - // Setup a parser that stores the XmlTag - parser = new BridgeXmlBlockParser(parser, null, false) { - @Override - public Object getViewCookie() { - return ((BridgeXmlBlockParser) getParser()).getViewCookie(); - } - - @Override - public int next() throws XmlPullParserException, IOException { - int ev = super.next(); - if (ev == XmlPullParser.START_TAG) { - viewCookie.add(this.getViewCookie()); - } - - return ev; - } - }; - } - - // Create the PreferenceInflater - Object inflatedPreference = - createInflatedPreference(callback, context, parser, preferenceScreen, - preferenceManager); - - // Setup the RecyclerView (set adapter and layout manager) - Object preferenceGroupAdapter = - createPreferenceGroupAdapter(callback, inflatedPreference); - - // Instead of just setting the group adapter as adapter for a RecyclerView, we manually - // get all the items and add them to a LinearLayout. This allows us to set the view - // cookies so the preferences are correctly linked to their XML. - LinearLayout listView = setUpPreferencesListView(bridgeContext, context, viewCookie, - preferenceGroupAdapter); - - ScrollView scrollView = new ScrollView(context); - scrollView.setLayoutParams( - new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); - scrollView.addView(listView); - - if (root != null) { - root.addView(scrollView); - } - - return scrollView; - } catch (ReflectionException e) { - return null; - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java deleted file mode 100644 index d7d16cf6d764..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.layoutlib.bridge.android.view; - -import android.util.DisplayMetrics; -import android.view.Display; -import android.view.Display.Mode; -import android.view.DisplayAdjustments; -import android.view.DisplayInfo; -import android.view.View; -import android.view.WindowManager; - -public class WindowManagerImpl implements WindowManager { - - private final DisplayMetrics mMetrics; - private final Display mDisplay; - - public WindowManagerImpl(DisplayMetrics metrics) { - mMetrics = metrics; - - DisplayInfo info = new DisplayInfo(); - info.logicalHeight = mMetrics.heightPixels; - info.logicalWidth = mMetrics.widthPixels; - info.supportedModes = new Mode[] { - new Mode(0, mMetrics.widthPixels, mMetrics.heightPixels, 60f) - }; - mDisplay = new Display(null, Display.DEFAULT_DISPLAY, info, - DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS); - } - - @Override - public Display getDefaultDisplay() { - return mDisplay; - } - - - @Override - public void addView(View arg0, android.view.ViewGroup.LayoutParams arg1) { - // pass - } - - @Override - public void removeView(View arg0) { - // pass - } - - @Override - public void updateViewLayout(View arg0, android.view.ViewGroup.LayoutParams arg1) { - // pass - } - - - @Override - public void removeViewImmediate(View arg0) { - // pass - } - - @Override - public void requestAppKeyboardShortcuts( - KeyboardShortcutsReceiver receiver, int deviceId) { - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java deleted file mode 100644 index cdcf0ea1ca76..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * 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 com.android.layoutlib.bridge.bars; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.ide.common.rendering.api.LayoutlibCallback; -import com.android.ide.common.rendering.api.RenderResources; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.rendering.api.SessionParams; -import com.android.ide.common.rendering.api.StyleResourceValue; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.impl.ResourceHelper; -import com.android.resources.ResourceType; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.view.ContextThemeWrapper; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.FrameLayout; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - - -/** - * Assumes that the AppCompat library is present in the project's classpath and creates an - * actionbar around it. - */ -public class AppCompatActionBar extends BridgeActionBar { - - private Object mWindowDecorActionBar; - private static final String WINDOW_ACTION_BAR_CLASS = "android.support.v7.internal.app.WindowDecorActionBar"; - // This is used on v23.1.1 and later. - private static final String WINDOW_ACTION_BAR_CLASS_NEW = "android.support.v7.app.WindowDecorActionBar"; - private Class<?> mWindowActionBarClass; - - /** - * Inflate the action bar and attach it to {@code parentView} - */ - public AppCompatActionBar(@NonNull BridgeContext context, @NonNull SessionParams params) { - super(context, params); - int contentRootId = context.getProjectResourceValue(ResourceType.ID, - "action_bar_activity_content", 0); - View contentView = getDecorContent().findViewById(contentRootId); - if (contentView != null) { - assert contentView instanceof FrameLayout; - setContentRoot((FrameLayout) contentView); - } else { - // Something went wrong. Create a new FrameLayout in the enclosing layout. - FrameLayout contentRoot = new FrameLayout(context); - setMatchParent(contentRoot); - if (mEnclosingLayout != null) { - mEnclosingLayout.addView(contentRoot); - } - setContentRoot(contentRoot); - } - try { - Class[] constructorParams = {View.class}; - Object[] constructorArgs = {getDecorContent()}; - LayoutlibCallback callback = params.getLayoutlibCallback(); - - // Check if the old action bar class is present. - String actionBarClass = WINDOW_ACTION_BAR_CLASS; - try { - callback.findClass(actionBarClass); - } catch (ClassNotFoundException expected) { - // Failed to find the old class, use the newer one. - actionBarClass = WINDOW_ACTION_BAR_CLASS_NEW; - } - - mWindowDecorActionBar = callback.loadView(actionBarClass, - constructorParams, constructorArgs); - mWindowActionBarClass = mWindowDecorActionBar == null ? null : - mWindowDecorActionBar.getClass(); - setupActionBar(); - } catch (Exception e) { - Bridge.getLog().warning(LayoutLog.TAG_BROKEN, - "Failed to load AppCompat ActionBar with unknown error.", e); - } - } - - @Override - protected ResourceValue getLayoutResource(BridgeContext context) { - // We always assume that the app has requested the action bar. - return context.getRenderResources().getProjectResource(ResourceType.LAYOUT, - "abc_screen_toolbar"); - } - - @Override - protected LayoutInflater getInflater(BridgeContext context) { - // Other than the resource resolution part, the code has been taken from the support - // library. see code from line 269 onwards in - // https://android.googlesource.com/platform/frameworks/support/+/android-5.1.0_r1/v7/appcompat/src/android/support/v7/app/ActionBarActivityDelegateBase.java - Context themedContext = context; - RenderResources resources = context.getRenderResources(); - ResourceValue actionBarTheme = resources.findItemInTheme("actionBarTheme", false); - if (actionBarTheme != null) { - // resolve it, if needed. - actionBarTheme = resources.resolveResValue(actionBarTheme); - } - if (actionBarTheme instanceof StyleResourceValue) { - int styleId = context.getDynamicIdByStyle(((StyleResourceValue) actionBarTheme)); - if (styleId != 0) { - themedContext = new ContextThemeWrapper(context, styleId); - } - } - return LayoutInflater.from(themedContext); - } - - @Override - protected void setTitle(CharSequence title) { - if (title != null && mWindowDecorActionBar != null) { - Method setTitle = getMethod(mWindowActionBarClass, "setTitle", CharSequence.class); - invoke(setTitle, mWindowDecorActionBar, title); - } - } - - @Override - protected void setSubtitle(CharSequence subtitle) { - if (subtitle != null && mWindowDecorActionBar != null) { - Method setSubtitle = getMethod(mWindowActionBarClass, "setSubtitle", CharSequence.class); - invoke(setSubtitle, mWindowDecorActionBar, subtitle); - } - } - - @Override - protected void setIcon(String icon) { - // Do this only if the action bar doesn't already have an icon. - if (icon != null && !icon.isEmpty() && mWindowDecorActionBar != null) { - if (invoke(getMethod(mWindowActionBarClass, "hasIcon"), mWindowDecorActionBar) - == Boolean.TRUE) { - Drawable iconDrawable = getDrawable(icon, false); - if (iconDrawable != null) { - Method setIcon = getMethod(mWindowActionBarClass, "setIcon", Drawable.class); - invoke(setIcon, mWindowDecorActionBar, iconDrawable); - } - } - } - } - - @Override - protected void setHomeAsUp(boolean homeAsUp) { - if (mWindowDecorActionBar != null) { - Method setHomeAsUp = getMethod(mWindowActionBarClass, - "setDefaultDisplayHomeAsUpEnabled", boolean.class); - invoke(setHomeAsUp, mWindowDecorActionBar, homeAsUp); - } - } - - @Override - public void createMenuPopup() { - // it's hard to add menus to appcompat's actionbar, since it'll use a lot of reflection. - // so we skip it for now. - } - - @Nullable - private static Method getMethod(Class<?> owner, String name, Class<?>... parameterTypes) { - try { - return owner == null ? null : owner.getMethod(name, parameterTypes); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } - return null; - } - - @Nullable - private static Object invoke(Method method, Object owner, Object... args) { - try { - return method == null ? null : method.invoke(owner, args); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - return null; - } - - // TODO: this is duplicated from FrameworkActionBarWrapper$WindowActionBarWrapper - @Nullable - private Drawable getDrawable(@NonNull String name, boolean isFramework) { - RenderResources res = mBridgeContext.getRenderResources(); - ResourceValue value = res.findResValue(name, isFramework); - value = res.resolveResValue(value); - if (value != null) { - return ResourceHelper.getDrawable(value, mBridgeContext); - } - return null; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/BridgeActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/BridgeActionBar.java deleted file mode 100644 index a439e7d034df..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/BridgeActionBar.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * 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 com.android.layoutlib.bridge.bars; - -import com.android.ide.common.rendering.api.ActionBarCallback; -import com.android.ide.common.rendering.api.ActionBarCallback.HomeButtonStyle; -import com.android.ide.common.rendering.api.RenderResources; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.rendering.api.SessionParams; -import com.android.layoutlib.bridge.MockView; -import com.android.layoutlib.bridge.android.BridgeContext; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewGroup.LayoutParams; -import android.widget.FrameLayout; -import android.widget.RelativeLayout; - -/** - * An abstraction over two implementations of the ActionBar - framework and appcompat. - */ -public abstract class BridgeActionBar { - // Store a reference to the context so that we don't have to cast it repeatedly. - @NonNull protected final BridgeContext mBridgeContext; - @NonNull protected final SessionParams mParams; - // A Layout that contains the inflated action bar. The menu popup is added to this layout. - @Nullable protected final ViewGroup mEnclosingLayout; - - private final View mDecorContent; - private final ActionBarCallback mCallback; - - @SuppressWarnings("NullableProblems") // Should be initialized by subclasses. - @NonNull private FrameLayout mContentRoot; - - public BridgeActionBar(@NonNull BridgeContext context, @NonNull SessionParams params) { - mBridgeContext = context; - mParams = params; - mCallback = params.getLayoutlibCallback().getActionBarCallback(); - ResourceValue layoutName = getLayoutResource(context); - - int layoutId = 0; - if (layoutName == null) { - assert false : "Unable to find the layout for Action Bar."; - } - else { - if (layoutName.isFramework()) { - layoutId = context.getFrameworkResourceValue(layoutName.getResourceType(), - layoutName.getName(), 0); - } else { - layoutId = context.getProjectResourceValue(layoutName.getResourceType(), - layoutName.getName(), 0); - - } - } - if (layoutId == 0) { - assert false : String.format("Unable to resolve attribute \"%1$s\" of type \"%2$s\"", - layoutName.getName(), layoutName.getResourceType()); - mDecorContent = new MockView(context); - mEnclosingLayout = null; - } - else { - if (mCallback.isOverflowPopupNeeded()) { - // Create a RelativeLayout around the action bar, to which the overflow popup may be - // added. - mEnclosingLayout = new RelativeLayout(mBridgeContext); - setMatchParent(mEnclosingLayout); - } else { - mEnclosingLayout = null; - } - - // Inflate action bar layout. - mDecorContent = getInflater(context).inflate(layoutId, mEnclosingLayout, - mEnclosingLayout != null); - } - } - - /** - * Returns the Layout Resource that should be used to inflate the action bar. This layout - * should cover the complete screen, and have a FrameLayout included, where the content will - * be inflated. - */ - protected abstract ResourceValue getLayoutResource(BridgeContext context); - - protected LayoutInflater getInflater(BridgeContext context) { - return LayoutInflater.from(context); - } - - protected void setContentRoot(@NonNull FrameLayout contentRoot) { - mContentRoot = contentRoot; - } - - @NonNull - public FrameLayout getContentRoot() { - return mContentRoot; - } - - /** - * Returns the view inflated. This should contain both the ActionBar and the app content in it. - */ - protected View getDecorContent() { - return mDecorContent; - } - - /** Setup things like the title, subtitle, icon etc. */ - protected void setupActionBar() { - setTitle(); - setSutTitle(); - setIcon(); - setHomeAsUp(mCallback.getHomeButtonStyle() == HomeButtonStyle.SHOW_HOME_AS_UP); - } - - protected abstract void setTitle(CharSequence title); - protected abstract void setSubtitle(CharSequence subtitle); - protected abstract void setIcon(String icon); - protected abstract void setHomeAsUp(boolean homeAsUp); - - private void setTitle() { - RenderResources res = mBridgeContext.getRenderResources(); - - String title = mParams.getAppLabel(); - ResourceValue titleValue = res.findResValue(title, false); - if (titleValue != null && titleValue.getValue() != null) { - setTitle(titleValue.getValue()); - } else { - setTitle(title); - } - } - - private void setSutTitle() { - String subTitle = mCallback.getSubTitle(); - if (subTitle != null) { - setSubtitle(subTitle); - } - } - - private void setIcon() { - String appIcon = mParams.getAppIcon(); - if (appIcon != null) { - setIcon(appIcon); - } - } - - public abstract void createMenuPopup(); - - /** - * The root view that represents the action bar and possibly the content included in it. - */ - public View getRootView() { - return mEnclosingLayout == null ? mDecorContent : mEnclosingLayout; - } - - public ActionBarCallback getCallBack() { - return mCallback; - } - - protected static void setMatchParent(View view) { - view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, - LayoutParams.MATCH_PARENT)); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java deleted file mode 100644 index 7f8d9928d7ce..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java +++ /dev/null @@ -1,137 +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 com.android.layoutlib.bridge.bars; - -import android.os._Original_Build.VERSION_CODES; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import static android.os._Original_Build.VERSION_CODES.*; - -/** - * Various helper methods to simulate older versions of platform. - */ -public class Config { - - // each of these resource dirs must end in '/' - private static final String GINGERBREAD_DIR = "/bars/v9/"; - private static final String JELLYBEAN_DIR = "/bars/v18/"; - private static final String KITKAT_DIR = "/bars/v19/"; - private static final String DEFAULT_RESOURCE_DIR = "/bars/v21/"; - - private static final List<String> sDefaultResourceDir = - Collections.singletonList(DEFAULT_RESOURCE_DIR); - - private static final int WHITE = 0xFFFFFFFF; - private static final int BLACK = 0xFF000000; - - public static boolean showOnScreenNavBar(int platformVersion) { - return isGreaterOrEqual(platformVersion, ICE_CREAM_SANDWICH); - } - - public static int getStatusBarColor(int platformVersion) { - // return white for froyo and earlier; black otherwise. - return isGreaterOrEqual(platformVersion, GINGERBREAD) ? BLACK : WHITE; - } - - public static List<String> getResourceDirs(int platformVersion) { - // Special case the most used scenario. - if (platformVersion == 0) { - return sDefaultResourceDir; - } - List<String> list = new ArrayList<String>(4); - // Gingerbread - uses custom battery and wifi icons. - if (platformVersion <= GINGERBREAD) { - list.add(GINGERBREAD_DIR); - } - // ICS - JellyBean uses custom battery, wifi. - if (platformVersion <= JELLY_BEAN_MR2) { - list.add(JELLYBEAN_DIR); - } - // KitKat - uses custom wifi and nav icons. - if (platformVersion <= KITKAT) { - list.add(KITKAT_DIR); - } - list.add(DEFAULT_RESOURCE_DIR); - - return Collections.unmodifiableList(list); - } - - public static String getTime(int platformVersion) { - if (isGreaterOrEqual(platformVersion, N)) { - return "7:00"; - } - if (platformVersion < GINGERBREAD) { - return "2:20"; - } - if (platformVersion < ICE_CREAM_SANDWICH) { - return "2:30"; - } - if (platformVersion < JELLY_BEAN) { - return "4:00"; - } - if (platformVersion < KITKAT) { - return "4:30"; - } - if (platformVersion < LOLLIPOP) { - return "4:40"; - } - if (platformVersion < LOLLIPOP_MR1) { - return "5:00"; - } - if (platformVersion < M) { - return "5:10"; - } - if (platformVersion < N) { - return "6:00"; - } - // Should never happen. - return "4:04"; - } - - public static int getTimeColor(int platformVersion) { - if (isGreaterOrEqual(platformVersion, KITKAT) || - platformVersion > FROYO && platformVersion < HONEYCOMB) { - // Gingerbread and KitKat onwards. - return WHITE; - } - // Black for froyo. - if (platformVersion < GINGERBREAD) { - return BLACK; - } else if (platformVersion < KITKAT) { - // Honeycomb to JB-mr2: Holo blue light. - return 0xff33b5e5; - } - // Should never happen. - return WHITE; - } - - public static String getWifiIconType(int platformVersion) { - return isGreaterOrEqual(platformVersion, LOLLIPOP) ? "xml" : "png"; - } - - /** - * Compare simulated platform version and code from {@link VERSION_CODES} to check if - * the simulated platform is greater than or equal to the version code. - */ - public static boolean isGreaterOrEqual(int platformVersion, int code) { - // simulated platform version = 0 means that we use the latest. - return platformVersion == 0 || platformVersion >= code; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java deleted file mode 100644 index 2984fc0e5abb..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.bars; - -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.ide.common.rendering.api.StyleResourceValue; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; -import com.android.layoutlib.bridge.impl.ParserFactory; -import com.android.layoutlib.bridge.impl.ResourceHelper; -import com.android.resources.Density; -import com.android.resources.LayoutDirection; -import com.android.resources.ResourceType; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import android.annotation.NonNull; -import android.content.res.ColorStateList; -import android.graphics.Bitmap; -import android.graphics.Bitmap_Delegate; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.util.TypedValue; -import android.view.Gravity; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -import java.io.IOException; -import java.io.InputStream; - -import static android.os._Original_Build.VERSION_CODES.LOLLIPOP; - -/** - * Base "bar" class for the window decor around the the edited layout. - * This is basically an horizontal layout that loads a given layout on creation (it is read - * through {@link Class#getResourceAsStream(String)}). - * - * The given layout should be a merge layout so that all the children belong to this class directly. - * - * It also provides a few utility methods to configure the content of the layout. - */ -abstract class CustomBar extends LinearLayout { - - - private final int mSimulatedPlatformVersion; - - protected abstract TextView getStyleableTextView(); - - protected CustomBar(BridgeContext context, int orientation, String layoutPath, - String name, int simulatedPlatformVersion) { - super(context); - mSimulatedPlatformVersion = simulatedPlatformVersion; - setOrientation(orientation); - if (orientation == LinearLayout.HORIZONTAL) { - setGravity(Gravity.CENTER_VERTICAL); - } else { - setGravity(Gravity.CENTER_HORIZONTAL); - } - - LayoutInflater inflater = LayoutInflater.from(mContext); - - XmlPullParser parser; - try { - parser = ParserFactory.create(getClass().getResourceAsStream(layoutPath), name); - - BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser(parser, context, false); - - try { - inflater.inflate(bridgeParser, this, true); - } finally { - bridgeParser.ensurePopped(); - } - } catch (XmlPullParserException e) { - // Should not happen as the resource is bundled with the jar, and ParserFactory should - // have been initialized. - assert false; - } - } - - protected void loadIcon(int index, String iconName, Density density) { - loadIcon(index, iconName, density, false); - } - - protected void loadIcon(int index, String iconName, Density density, boolean isRtl) { - View child = getChildAt(index); - if (child instanceof ImageView) { - ImageView imageView = (ImageView) child; - - LayoutDirection dir = isRtl ? LayoutDirection.RTL : null; - IconLoader iconLoader = new IconLoader(iconName, density, mSimulatedPlatformVersion, - dir); - InputStream stream = iconLoader.getIcon(); - - if (stream != null) { - density = iconLoader.getDensity(); - String path = iconLoader.getPath(); - // look for a cached bitmap - Bitmap bitmap = Bridge.getCachedBitmap(path, Boolean.TRUE /*isFramework*/); - if (bitmap == null) { - try { - bitmap = Bitmap_Delegate.createBitmap(stream, false /*isMutable*/, density); - Bridge.setCachedBitmap(path, bitmap, Boolean.TRUE /*isFramework*/); - } catch (IOException e) { - return; - } - } - - if (bitmap != null) { - BitmapDrawable drawable = new BitmapDrawable(getContext().getResources(), - bitmap); - imageView.setImageDrawable(drawable); - } - } - } - } - - protected TextView setText(int index, String string, boolean reference) { - View child = getChildAt(index); - if (child instanceof TextView) { - TextView textView = (TextView) child; - setText(textView, string, reference); - return textView; - } - - return null; - } - - private void setText(TextView textView, String string, boolean reference) { - if (reference) { - ResourceValue value = getResourceValue(string); - if (value != null) { - string = value.getValue(); - } - } - textView.setText(string); - } - - protected void setStyle(String themeEntryName) { - - BridgeContext bridgeContext = getContext(); - RenderResources res = bridgeContext.getRenderResources(); - - ResourceValue value = res.findItemInTheme(themeEntryName, true /*isFrameworkAttr*/); - value = res.resolveResValue(value); - - if (!(value instanceof StyleResourceValue)) { - return; - } - - StyleResourceValue style = (StyleResourceValue) value; - - // get the background - ResourceValue backgroundValue = res.findItemInStyle(style, "background", - true /*isFrameworkAttr*/); - backgroundValue = res.resolveResValue(backgroundValue); - if (backgroundValue != null) { - Drawable d = ResourceHelper.getDrawable(backgroundValue, bridgeContext); - if (d != null) { - setBackground(d); - } - } - - TextView textView = getStyleableTextView(); - if (textView != null) { - // get the text style - ResourceValue textStyleValue = res.findItemInStyle(style, "titleTextStyle", - true /*isFrameworkAttr*/); - textStyleValue = res.resolveResValue(textStyleValue); - if (textStyleValue instanceof StyleResourceValue) { - StyleResourceValue textStyle = (StyleResourceValue) textStyleValue; - - ResourceValue textSize = res.findItemInStyle(textStyle, "textSize", - true /*isFrameworkAttr*/); - textSize = res.resolveResValue(textSize); - - if (textSize != null) { - TypedValue out = new TypedValue(); - if (ResourceHelper.parseFloatAttribute("textSize", textSize.getValue(), out, - true /*requireUnit*/)) { - textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, - out.getDimension(bridgeContext.getResources().getDisplayMetrics())); - } - } - - - ResourceValue textColor = res.findItemInStyle(textStyle, "textColor", - true); - textColor = res.resolveResValue(textColor); - if (textColor != null) { - ColorStateList stateList = ResourceHelper.getColorStateList( - textColor, bridgeContext); - if (stateList != null) { - textView.setTextColor(stateList); - } - } - } - } - } - - @Override - public BridgeContext getContext() { - return (BridgeContext) mContext; - } - - /** - * Find the background color for this bar from the theme attributes. Only relevant to StatusBar - * and NavigationBar. - * <p/> - * Returns 0 if not found. - * - * @param colorAttrName the attribute name for the background color - * @param translucentAttrName the attribute name for the translucency property of the bar. - * - * @throws NumberFormatException if color resolved to an invalid string. - */ - protected int getBarColor(@NonNull String colorAttrName, @NonNull String translucentAttrName) { - if (!Config.isGreaterOrEqual(mSimulatedPlatformVersion, LOLLIPOP)) { - return 0; - } - RenderResources renderResources = getContext().getRenderResources(); - // First check if the bar is translucent. - boolean translucent = ResourceHelper.getBooleanThemeValue(renderResources, - translucentAttrName, true, false); - if (translucent) { - // Keep in sync with R.color.system_bar_background_semi_transparent from system ui. - return 0x66000000; // 40% black. - } - boolean transparent = ResourceHelper.getBooleanThemeValue(renderResources, - "windowDrawsSystemBarBackgrounds", true, false); - if (transparent) { - return getColor(renderResources, colorAttrName); - } - return 0; - } - - private static int getColor(RenderResources renderResources, String attr) { - // From ?attr/foo to @color/bar. This is most likely an ItemResourceValue. - ResourceValue resource = renderResources.findItemInTheme(attr, true); - // Form @color/bar to the #AARRGGBB - resource = renderResources.resolveResValue(resource); - if (resource != null) { - ResourceType type = resource.getResourceType(); - if (type == null || type == ResourceType.COLOR) { - // if no type is specified, the value may have been specified directly in the style - // file, rather than referencing a color resource value. - try { - return ResourceHelper.getColor(resource.getValue()); - } catch (NumberFormatException e) { - // Conversion failed. - Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT, - "Theme attribute @android:" + attr + - " does not reference a color, instead is '" + - resource.getValue() + "'.", resource); - } - } - } - return 0; - } - - private ResourceValue getResourceValue(String reference) { - RenderResources res = getContext().getRenderResources(); - - // find the resource - ResourceValue value = res.findResValue(reference, false); - - // resolve it if needed - return res.resolveResValue(value); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBar.java deleted file mode 100644 index fd49c7700ea9..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBar.java +++ /dev/null @@ -1,258 +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 com.android.layoutlib.bridge.bars; - -import com.android.ide.common.rendering.api.RenderResources; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.rendering.api.SessionParams; -import com.android.internal.R; -import com.android.internal.view.menu.MenuBuilder; -import com.android.internal.view.menu.MenuItemImpl; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.impl.ResourceHelper; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.content.res.TypedArray; -import android.util.DisplayMetrics; -import android.util.TypedValue; -import android.view.InflateException; -import android.view.View; -import android.view.View.MeasureSpec; -import android.view.ViewGroup; -import android.view.ViewGroup.LayoutParams; -import android.widget.ActionMenuPresenter; -import android.widget.FrameLayout; -import android.widget.ListAdapter; -import android.widget.ListView; -import android.widget.RelativeLayout; - -import java.util.ArrayList; - -/** - * Creates the ActionBar as done by the framework. - */ -public class FrameworkActionBar extends BridgeActionBar { - - private static final String LAYOUT_ATTR_NAME = "windowActionBarFullscreenDecorLayout"; - - // The Action Bar - @NonNull private FrameworkActionBarWrapper mActionBar; - - // A fake parent for measuring views. - @Nullable private ViewGroup mMeasureParent; - - /** - * Inflate the action bar and attach it to {@code parentView} - */ - public FrameworkActionBar(@NonNull BridgeContext context, @NonNull SessionParams params) { - super(context, params); - - View decorContent = getDecorContent(); - - mActionBar = FrameworkActionBarWrapper.getActionBarWrapper(context, getCallBack(), - decorContent); - - FrameLayout contentRoot = (FrameLayout) decorContent.findViewById(android.R.id.content); - - // If something went wrong and we were not able to initialize the content root, - // just add a frame layout inside this and return. - if (contentRoot == null) { - contentRoot = new FrameLayout(context); - setMatchParent(contentRoot); - if (mEnclosingLayout != null) { - mEnclosingLayout.addView(contentRoot); - } - setContentRoot(contentRoot); - } else { - setContentRoot(contentRoot); - setupActionBar(); - mActionBar.inflateMenus(); - } - } - - @Override - protected ResourceValue getLayoutResource(BridgeContext context) { - ResourceValue layoutName = - context.getRenderResources().findItemInTheme(LAYOUT_ATTR_NAME, true); - if (layoutName != null) { - // We may need to resolve the reference obtained. - layoutName = context.getRenderResources().findResValue(layoutName.getValue(), - layoutName.isFramework()); - } - if (layoutName == null) { - throw new InflateException("Unable to find action bar layout (" + LAYOUT_ATTR_NAME - + ") in the current theme."); - } - return layoutName; - } - - @Override - protected void setupActionBar() { - super.setupActionBar(); - mActionBar.setupActionBar(); - } - - @Override - protected void setHomeAsUp(boolean homeAsUp) { - mActionBar.setHomeAsUp(homeAsUp); - } - - @Override - protected void setTitle(CharSequence title) { - mActionBar.setTitle(title); - } - - @Override - protected void setSubtitle(CharSequence subtitle) { - mActionBar.setSubTitle(subtitle); - } - - @Override - protected void setIcon(String icon) { - mActionBar.setIcon(icon); - } - - /** - * Creates a Popup and adds it to the content frame. It also adds another {@link FrameLayout} to - * the content frame which shall serve as the new content root. - */ - @Override - public void createMenuPopup() { - if (!isOverflowPopupNeeded()) { - return; - } - - DisplayMetrics metrics = mBridgeContext.getMetrics(); - MenuBuilder menu = mActionBar.getMenuBuilder(); - OverflowMenuAdapter adapter = new OverflowMenuAdapter(menu, mActionBar.getPopupContext()); - - ListView listView = new ListView(mActionBar.getPopupContext(), null, - R.attr.dropDownListViewStyle); - RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams( - measureContentWidth(adapter), LayoutParams.WRAP_CONTENT); - layoutParams.addRule(RelativeLayout.ALIGN_PARENT_END); - if (mActionBar.isSplit()) { - layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); - layoutParams.bottomMargin = getActionBarHeight() + mActionBar.getMenuPopupMargin(); - } else { - layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP); - layoutParams.topMargin = getActionBarHeight() + mActionBar.getMenuPopupMargin(); - } - layoutParams.setMarginEnd(getPixelValue("5dp", metrics)); - listView.setLayoutParams(layoutParams); - listView.setAdapter(adapter); - final TypedArray a = mActionBar.getPopupContext().obtainStyledAttributes(null, - R.styleable.PopupWindow, R.attr.popupMenuStyle, 0); - listView.setBackground(a.getDrawable(R.styleable.PopupWindow_popupBackground)); - listView.setDivider(a.getDrawable(R.attr.actionBarDivider)); - a.recycle(); - listView.setElevation(mActionBar.getMenuPopupElevation()); - assert mEnclosingLayout != null : "Unable to find view to attach ActionMenuPopup."; - mEnclosingLayout.addView(listView); - } - - private boolean isOverflowPopupNeeded() { - boolean needed = mActionBar.isOverflowPopupNeeded(); - if (!needed) { - return false; - } - // Copied from android.widget.ActionMenuPresenter.updateMenuView() - ArrayList<MenuItemImpl> menus = mActionBar.getMenuBuilder().getNonActionItems(); - ActionMenuPresenter presenter = mActionBar.getActionMenuPresenter(); - if (presenter == null) { - assert false : "Failed to create a Presenter for Action Bar Menus."; - return false; - } - if (presenter.isOverflowReserved() && - menus != null) { - final int count = menus.size(); - if (count == 1) { - needed = !menus.get(0).isActionViewExpanded(); - } else { - needed = count > 0; - } - } - return needed; - } - - // Copied from com.android.internal.view.menu.MenuPopHelper.measureContentWidth() - private int measureContentWidth(@NonNull ListAdapter adapter) { - // Menus don't tend to be long, so this is more sane than it looks. - int maxWidth = 0; - View itemView = null; - int itemType = 0; - - Context context = mActionBar.getPopupContext(); - final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); - final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); - final int count = adapter.getCount(); - for (int i = 0; i < count; i++) { - final int positionType = adapter.getItemViewType(i); - if (positionType != itemType) { - itemType = positionType; - itemView = null; - } - - if (mMeasureParent == null) { - mMeasureParent = new FrameLayout(context); - } - - itemView = adapter.getView(i, itemView, mMeasureParent); - itemView.measure(widthMeasureSpec, heightMeasureSpec); - - final int itemWidth = itemView.getMeasuredWidth(); - int popupMaxWidth = Math.max(mBridgeContext.getMetrics().widthPixels / 2, - context.getResources().getDimensionPixelSize(R.dimen.config_prefDialogWidth)); - if (itemWidth >= popupMaxWidth) { - return popupMaxWidth; - } else if (itemWidth > maxWidth) { - maxWidth = itemWidth; - } - } - - return maxWidth; - } - - static int getPixelValue(@NonNull String value, @NonNull DisplayMetrics metrics) { - TypedValue typedValue = ResourceHelper.getValue(null, value, false /*requireUnit*/); - return (int) typedValue.getDimension(metrics); - } - - // TODO: This is duplicated from RenderSessionImpl. - private int getActionBarHeight() { - RenderResources resources = mBridgeContext.getRenderResources(); - DisplayMetrics metrics = mBridgeContext.getMetrics(); - ResourceValue value = resources.findItemInTheme("actionBarSize", true); - - // resolve it - value = resources.resolveResValue(value); - - if (value != null) { - // get the numerical value, if available - TypedValue typedValue = ResourceHelper.getValue("actionBarSize", value.getValue(), - true); - if (typedValue != null) { - // compute the pixel value based on the display metrics - return (int) typedValue.getDimension(metrics); - - } - } - return 0; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBarWrapper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBarWrapper.java deleted file mode 100644 index 2cdc647b7996..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBarWrapper.java +++ /dev/null @@ -1,379 +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 com.android.layoutlib.bridge.bars; - -import com.android.ide.common.rendering.api.ActionBarCallback; -import com.android.ide.common.rendering.api.RenderResources; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.internal.R; -import com.android.internal.app.ToolbarActionBar; -import com.android.internal.app.WindowDecorActionBar; -import com.android.internal.view.menu.MenuBuilder; -import com.android.internal.widget.ActionBarAccessor; -import com.android.internal.widget.ActionBarView; -import com.android.internal.widget.DecorToolbar; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.impl.ResourceHelper; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.app.ActionBar; -import android.app.ActionBar.Tab; -import android.app.ActionBar.TabListener; -import android.app.FragmentTransaction; -import android.content.Context; -import android.content.res.Resources; -import android.graphics.drawable.Drawable; -import android.view.MenuInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.WindowCallback; -import android.widget.ActionMenuPresenter; -import android.widget.ActionMenuView; -import android.widget.Toolbar; -import android.widget.Toolbar_Accessor; - -import static com.android.SdkConstants.ANDROID_NS_NAME_PREFIX; -import static com.android.resources.ResourceType.MENU; - -/** - * A common API to access {@link ToolbarActionBar} and {@link WindowDecorActionBar}. - */ -public abstract class FrameworkActionBarWrapper { - - @NonNull protected ActionBar mActionBar; - @NonNull protected ActionBarCallback mCallback; - @NonNull protected BridgeContext mContext; - - /** - * Returns a wrapper around different implementations of the Action Bar to provide a common API. - * - * @param decorContent the top level view returned by inflating - * ?attr/windowActionBarFullscreenDecorLayout - */ - @NonNull - public static FrameworkActionBarWrapper getActionBarWrapper(@NonNull BridgeContext context, - @NonNull ActionBarCallback callback, @NonNull View decorContent) { - View view = decorContent.findViewById(R.id.action_bar); - if (view instanceof Toolbar) { - return new ToolbarWrapper(context, callback, (Toolbar) view); - } else if (view instanceof ActionBarView) { - return new WindowActionBarWrapper(context, callback, decorContent, - (ActionBarView) view); - } else { - throw new IllegalStateException("Can't make an action bar out of " + - view.getClass().getSimpleName()); - } - } - - FrameworkActionBarWrapper(@NonNull BridgeContext context, @NonNull ActionBarCallback callback, - @NonNull ActionBar actionBar) { - mActionBar = actionBar; - mCallback = callback; - mContext = context; - } - - /** A call to setup any custom properties. */ - protected void setupActionBar() { - // Nothing to do here. - } - - public void setTitle(CharSequence title) { - mActionBar.setTitle(title); - } - - public void setSubTitle(CharSequence subTitle) { - if (subTitle != null) { - mActionBar.setSubtitle(subTitle); - } - } - - public void setHomeAsUp(boolean homeAsUp) { - mActionBar.setDisplayHomeAsUpEnabled(homeAsUp); - } - - public void setIcon(String icon) { - // Nothing to do. - } - - protected boolean isSplit() { - return getDecorToolbar().isSplit(); - } - - protected boolean isOverflowPopupNeeded() { - return mCallback.isOverflowPopupNeeded(); - } - - /** - * Gets the menus to add to the action bar from the callback, resolves them, inflates them and - * adds them to the action bar. - */ - protected void inflateMenus() { - MenuInflater inflater = new MenuInflater(getActionMenuContext()); - MenuBuilder menuBuilder = getMenuBuilder(); - for (String name : mCallback.getMenuIdNames()) { - int id; - if (name.startsWith(ANDROID_NS_NAME_PREFIX)) { - // Framework menu. - name = name.substring(ANDROID_NS_NAME_PREFIX.length()); - id = mContext.getFrameworkResourceValue(MENU, name, -1); - } else { - // Project menu. - id = mContext.getProjectResourceValue(MENU, name, -1); - } - if (id > -1) { - inflater.inflate(id, menuBuilder); - } - } - } - - /** - * The context used for the ActionBar and the menus in the ActionBarView. - */ - @NonNull - protected Context getActionMenuContext() { - return mActionBar.getThemedContext(); - } - - /** - * The context used to inflate the popup menu. - */ - @NonNull - abstract Context getPopupContext(); - - /** - * The Menu in which to inflate the user's menus. - */ - @NonNull - abstract MenuBuilder getMenuBuilder(); - - @Nullable - abstract ActionMenuPresenter getActionMenuPresenter(); - - /** - * Framework's wrapper over two ActionBar implementations. - */ - @NonNull - abstract DecorToolbar getDecorToolbar(); - - abstract int getMenuPopupElevation(); - - /** - * Margin between the menu popup and the action bar. - */ - abstract int getMenuPopupMargin(); - - // ---- The implementations ---- - - /** - * Material theme uses {@link Toolbar} as the action bar. This wrapper provides access to - * Toolbar using a common API. - */ - private static class ToolbarWrapper extends FrameworkActionBarWrapper { - - @NonNull - private final Toolbar mToolbar; // This is the view. - - ToolbarWrapper(@NonNull BridgeContext context, @NonNull ActionBarCallback callback, - @NonNull Toolbar toolbar) { - super(context, callback, new ToolbarActionBar(toolbar, "", new WindowCallback())); - mToolbar = toolbar; - } - - @Override - protected void inflateMenus() { - super.inflateMenus(); - // Inflating the menus isn't enough. ActionMenuPresenter needs to be initialized too. - MenuBuilder menu = getMenuBuilder(); - DecorToolbar decorToolbar = getDecorToolbar(); - // Setting a menu different from the above initializes the presenter. - decorToolbar.setMenu(new MenuBuilder(getActionMenuContext()), null); - // ActionMenuView needs to be recreated to be able to set the menu back. - ActionMenuPresenter presenter = getActionMenuPresenter(); - if (presenter != null) { - presenter.setMenuView(new ActionMenuView(getPopupContext())); - } - decorToolbar.setMenu(menu, null); - } - - @NonNull - @Override - Context getPopupContext() { - return Toolbar_Accessor.getPopupContext(mToolbar); - } - - @NonNull - @Override - MenuBuilder getMenuBuilder() { - return (MenuBuilder) mToolbar.getMenu(); - } - - @Nullable - @Override - ActionMenuPresenter getActionMenuPresenter() { - return Toolbar_Accessor.getActionMenuPresenter(mToolbar); - } - - @NonNull - @Override - DecorToolbar getDecorToolbar() { - return mToolbar.getWrapper(); - } - - @Override - int getMenuPopupElevation() { - return 10; - } - - @Override - int getMenuPopupMargin() { - return 0; - } - } - - /** - * Holo theme uses {@link WindowDecorActionBar} as the action bar. This wrapper provides - * access to it using a common API. - */ - private static class WindowActionBarWrapper extends FrameworkActionBarWrapper { - - @NonNull private final WindowDecorActionBar mActionBar; - @NonNull private final ActionBarView mActionBarView; - @NonNull private final View mDecorContentRoot; - private MenuBuilder mMenuBuilder; - - public WindowActionBarWrapper(@NonNull BridgeContext context, - @NonNull ActionBarCallback callback, @NonNull View decorContentRoot, - @NonNull ActionBarView actionBarView) { - super(context, callback, new WindowDecorActionBar(decorContentRoot)); - mActionBarView = actionBarView; - mActionBar = (WindowDecorActionBar) super.mActionBar; - mDecorContentRoot = decorContentRoot; - } - - @Override - protected void setupActionBar() { - - // Set the navigation mode. - int navMode = mCallback.getNavigationMode(); - mActionBar.setNavigationMode(navMode); - //noinspection deprecation - if (navMode == ActionBar.NAVIGATION_MODE_TABS) { - setupTabs(3); - } - - // Set action bar to be split, if needed. - ViewGroup splitView = (ViewGroup) mDecorContentRoot.findViewById(R.id.split_action_bar); - if (splitView != null) { - mActionBarView.setSplitView(splitView); - Resources res = mContext.getResources(); - boolean split = res.getBoolean(R.bool.split_action_bar_is_narrow) - && mCallback.getSplitActionBarWhenNarrow(); - mActionBarView.setSplitToolbar(split); - } - } - - @Override - public void setIcon(String icon) { - // Set the icon only if the action bar doesn't specify an icon. - if (!mActionBar.hasIcon() && icon != null) { - Drawable iconDrawable = getDrawable(icon, false); - if (iconDrawable != null) { - mActionBar.setIcon(iconDrawable); - } - } - } - - @Override - protected void inflateMenus() { - super.inflateMenus(); - // The super implementation doesn't set the menu on the view. Set it here. - mActionBarView.setMenu(getMenuBuilder(), null); - } - - @NonNull - @Override - Context getPopupContext() { - return getActionMenuContext(); - } - - @NonNull - @Override - MenuBuilder getMenuBuilder() { - if (mMenuBuilder == null) { - mMenuBuilder = new MenuBuilder(getActionMenuContext()); - } - return mMenuBuilder; - } - - @Nullable - @Override - ActionMenuPresenter getActionMenuPresenter() { - return ActionBarAccessor.getActionMenuPresenter(mActionBarView); - } - - @NonNull - @Override - ActionBarView getDecorToolbar() { - return mActionBarView; - } - - @Override - int getMenuPopupElevation() { - return 0; - } - - @Override - int getMenuPopupMargin() { - return -FrameworkActionBar.getPixelValue("10dp", mContext.getMetrics()); - } - - // TODO: Use an adapter, like List View to set up tabs. - @SuppressWarnings("deprecation") // For Tab - private void setupTabs(int num) { - for (int i = 1; i <= num; i++) { - Tab tab = mActionBar.newTab().setText("Tab" + i).setTabListener(new TabListener() { - @Override - public void onTabUnselected(Tab t, FragmentTransaction ft) { - // pass - } - @Override - public void onTabSelected(Tab t, FragmentTransaction ft) { - // pass - } - @Override - public void onTabReselected(Tab t, FragmentTransaction ft) { - // pass - } - }); - mActionBar.addTab(tab); - } - } - - @Nullable - private Drawable getDrawable(@NonNull String name, boolean isFramework) { - RenderResources res = mContext.getRenderResources(); - ResourceValue value = res.findResValue(name, isFramework); - value = res.resolveResValue(value); - if (value != null) { - return ResourceHelper.getDrawable(value, mContext); - } - return null; - } - - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/IconLoader.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/IconLoader.java deleted file mode 100644 index 9ab2e82f00c8..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/IconLoader.java +++ /dev/null @@ -1,125 +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 com.android.layoutlib.bridge.bars; - -import com.android.resources.Density; -import com.android.resources.LayoutDirection; - -import java.io.InputStream; - -public class IconLoader { - - private final String mIconName; - private final Density mDesiredDensity; - private final int mPlatformVersion; - private final LayoutDirection mDirection; - - private Density mCurrentDensity; - private StringBuilder mCurrentPath; - - IconLoader(String iconName, Density density, int platformVersion, LayoutDirection direction) { - mIconName = iconName; - mDesiredDensity = density; - mPlatformVersion = platformVersion; - mDirection = direction; - // An upper bound on the length of the path for the icon: /bars/v21/ldrtl-xxxhdpi/ - final int iconPathLength = 24; - mCurrentPath = new StringBuilder(iconPathLength + iconName.length()); - } - - public InputStream getIcon() { - for (String resourceDir : Config.getResourceDirs(mPlatformVersion)) { - mCurrentDensity = null; - InputStream stream = getIcon(resourceDir); - if (stream != null) { - return stream; - } - } - return null; - } - - /** - * Should only be called after {@link #getIcon()}. Returns the density of the icon, if found by - * {@code getIcon()}. If no icon was found, then the return value has no meaning. - */ - public Density getDensity() { - return mCurrentDensity; - } - - /** - * Should only be called after {@link #getIcon()}. Returns the path to the icon, if found by - * {@code getIcon()}. If no icon was found, then the return value has no meaning. - */ - public String getPath() { - return mCurrentPath.toString(); - } - - /** - * Search for icon in the resource directory. This iterates over all densities. - * If a match is found, mCurrentDensity will be set to the icon's density. - */ - private InputStream getIcon(String resourceDir) { - // First check for the desired density. - InputStream stream = getIcon(resourceDir, mDesiredDensity); - if (stream != null) { - mCurrentDensity = mDesiredDensity; - return stream; - } - // Didn't find in the desired density. Search in all. - for (Density density : Density.values()) { - if (density == mDesiredDensity) { - // Skip the desired density since it's already been checked. - continue; - } - stream = getIcon(resourceDir, density); - if (stream != null) { - mCurrentDensity = density; - return stream; - } - } - return null; - } - - /** - * Returns the icon for given density present in the given resource directory, taking layout - * direction into consideration. - */ - private InputStream getIcon(String resourceDir, Density density) { - mCurrentPath.setLength(0); - // Currently we don't have any LTR only resources and hence the check is skipped. If they - // are ever added, change to: - // if (mDirection == LayoutDirection.RTL || mDirection == LayoutDirection.LTR) { - if (mDirection == LayoutDirection.RTL) { - mCurrentPath.append(resourceDir) - .append(mDirection.getResourceValue()) - .append('-') - .append(density.getResourceValue()) - .append('/') - .append(mIconName); - InputStream stream = getClass().getResourceAsStream(mCurrentPath.toString()); - if (stream != null) { - return stream; - } - mCurrentPath.setLength(0); - } - mCurrentPath.append(resourceDir) - .append(density.getResourceValue()) - .append('/') - .append(mIconName); - return getClass().getResourceAsStream(mCurrentPath.toString()); - } -} 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 deleted file mode 100644 index dfbc69bee59c..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.bars; - -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.resources.Density; - -import android.util.DisplayMetrics; -import android.view.View; -import android.widget.LinearLayout; -import android.widget.TextView; - -public class NavigationBar extends CustomBar { - - /** Navigation bar background color attribute name. */ - private static final String ATTR_COLOR = "navigationBarColor"; - /** Attribute for translucency property. */ - public static final String ATTR_TRANSLUCENT = "windowTranslucentNavigation"; - // 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; - protected static final String LAYOUT_XML = "/bars/navigation_bar.xml"; - private static final String LAYOUT_600DP_XML = "/bars/navigation_bar600dp.xml"; - - public NavigationBar(BridgeContext context, Density density, int orientation, boolean isRtl, - boolean rtlEnabled, int simulatedPlatformVersion) { - this(context, density, orientation, isRtl, rtlEnabled, simulatedPlatformVersion, - getShortestWidth(context)>= 600 ? LAYOUT_600DP_XML : LAYOUT_XML); - } - - protected NavigationBar(BridgeContext context, Density density, int orientation, boolean isRtl, - boolean rtlEnabled, int simulatedPlatformVersion, String layoutPath) { - super(context, orientation, layoutPath, "navigation_bar.xml", simulatedPlatformVersion); - - int color = getBarColor(ATTR_COLOR, ATTR_TRANSLUCENT); - setBackgroundColor(color == 0 ? 0xFF000000 : color); - - // Cannot access the inside items through id because no R.id values have been - // created for them. - // We do know the order though. - // 0 is a spacer. - int back = 1; - int recent = 5; - if (orientation == LinearLayout.VERTICAL || (isRtl && !rtlEnabled)) { - // If RTL is enabled, then layoutlib mirrors the layout for us. - back = 5; - recent = 1; - } - - //noinspection SpellCheckingInspection - loadIcon(back, "ic_sysbar_back.png", density, isRtl); - //noinspection SpellCheckingInspection - 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) { - float sw = getShortestWidth(context); - View leftPadding = getChildAt(0); - View rightPadding = getChildAt(6); - setSize(context, leftPadding, orientation, getSidePadding(sw)); - setSize(context, rightPadding, orientation, getSidePadding(sw)); - int navButtonWidth = getWidth(sw); - for (int i = 1; i < 6; i += 2) { - View navButton = getChildAt(i); - setSize(context, navButton, orientation, navButtonWidth); - } - if (sw >= 600) { - setSize(context, getChildAt(2), orientation, 128); - setSize(context, getChildAt(4), orientation, 128); - } - } - - 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); - } - - protected int getSidePadding(float sw) { - if (sw >= 400) { - return PADDING_WIDTH_SW400; - } - if (sw >= 360) { - return PADDING_WIDTH_SW360; - } - return PADDING_WIDTH_DEFAULT; - } - - private static int getWidth(float sw) { - if (sw >= 600) { - return WIDTH_SW600; - } - if (sw >= 360) { - return WIDTH_SW360; - } - return WIDTH_DEFAULT; - } - - private static float getShortestWidth(BridgeContext context) { - DisplayMetrics metrics = context.getMetrics(); - float sw = metrics.widthPixels < metrics.heightPixels ? - metrics.widthPixels : metrics.heightPixels; - sw /= metrics.density; - return sw; - } - - @Override - protected TextView getStyleableTextView() { - return null; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/OverflowMenuAdapter.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/OverflowMenuAdapter.java deleted file mode 100644 index 778305da6d70..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/OverflowMenuAdapter.java +++ /dev/null @@ -1,99 +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 com.android.layoutlib.bridge.bars; - -import com.android.internal.view.menu.MenuBuilder; -import com.android.internal.view.menu.MenuItemImpl; -import com.android.internal.view.menu.MenuView; - -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; - -import java.util.ArrayList; - -/** - * Provides an adapter for Overflow menu popup. This is very similar to - * {@code MenuPopupHelper.MenuAdapter} - */ -public class OverflowMenuAdapter extends BaseAdapter { - - private final MenuBuilder mMenu; - private int mExpandedIndex = -1; - private final Context context; - - public OverflowMenuAdapter(MenuBuilder menu, Context context) { - mMenu = menu; - findExpandedIndex(); - this.context = context; - } - - @Override - public int getCount() { - ArrayList<MenuItemImpl> items = mMenu.getNonActionItems(); - if (mExpandedIndex < 0) { - return items.size(); - } - return items.size() - 1; - } - - @Override - public MenuItemImpl getItem(int position) { - ArrayList<MenuItemImpl> items = mMenu.getNonActionItems(); - if (mExpandedIndex >= 0 && position >= mExpandedIndex) { - position++; - } - return items.get(position); - } - - @Override - public long getItemId(int position) { - // Since a menu item's ID is optional, we'll use the position as an - // ID for the item in the AdapterView - return position; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - if (convertView == null) { - LayoutInflater mInflater = LayoutInflater.from(context); - convertView = mInflater.inflate(com.android.internal.R.layout.popup_menu_item_layout, - parent, false); - } - - MenuView.ItemView itemView = (MenuView.ItemView) convertView; - itemView.initialize(getItem(position), 0); - return convertView; - } - - private void findExpandedIndex() { - final MenuItemImpl expandedItem = mMenu.getExpandedItem(); - if (expandedItem != null) { - final ArrayList<MenuItemImpl> items = mMenu.getNonActionItems(); - final int count = items.size(); - for (int i = 0; i < count; i++) { - final MenuItemImpl item = items.get(i); - if (item == expandedItem) { - mExpandedIndex = i; - return; - } - } - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java deleted file mode 100644 index 2dc7c65e2085..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.bars; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; -import com.android.layoutlib.bridge.impl.ParserFactory; -import com.android.resources.Density; - -import org.xmlpull.v1.XmlPullParserException; - -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; -import android.view.Gravity; -import android.view.View; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -import java.io.IOException; -import java.io.InputStream; - -public class StatusBar extends CustomBar { - - private final int mSimulatedPlatformVersion; - /** Status bar background color attribute name. */ - private static final String ATTR_COLOR = "statusBarColor"; - /** Attribute for translucency property. */ - public static final String ATTR_TRANSLUCENT = "windowTranslucentStatus"; - - /** - * Constructor to be used when creating the {@link StatusBar} as a regular control. This - * is currently used by the theme editor. - */ - @SuppressWarnings("UnusedParameters") - public StatusBar(Context context, AttributeSet attrs) { - this((BridgeContext) context, - Density.getEnum(((BridgeContext) context).getMetrics().densityDpi), - ((BridgeContext) context).getConfiguration().getLayoutDirection() == - View.LAYOUT_DIRECTION_RTL, - (context.getApplicationInfo().flags & ApplicationInfo.FLAG_SUPPORTS_RTL) != 0, - context.getApplicationInfo().targetSdkVersion); - } - - @SuppressWarnings("UnusedParameters") - public StatusBar(BridgeContext context, Density density, boolean isRtl, boolean rtlEnabled, - int simulatedPlatformVersion) { - // FIXME: if direction is RTL but it's not enabled in application manifest, mirror this bar. - super(context, LinearLayout.HORIZONTAL, "/bars/status_bar.xml", "status_bar.xml", - simulatedPlatformVersion); - mSimulatedPlatformVersion = simulatedPlatformVersion; - - // FIXME: use FILL_H? - setGravity(Gravity.START | Gravity.TOP | Gravity.RIGHT); - - int color = getBarColor(ATTR_COLOR, ATTR_TRANSLUCENT); - setBackgroundColor(color == 0 ? Config.getStatusBarColor(simulatedPlatformVersion) : color); - - // Cannot access the inside items through id because no R.id values have been - // created for them. - // We do know the order though. - // 0 is the spacer - loadIcon(1, "stat_sys_wifi_signal_4_fully." - + Config.getWifiIconType(simulatedPlatformVersion), density); - loadIcon(2, "stat_sys_battery_100.png", density); - setText(3, Config.getTime(simulatedPlatformVersion), false) - .setTextColor(Config.getTimeColor(simulatedPlatformVersion)); - } - - @Override - protected void loadIcon(int index, String iconName, Density density) { - if (!iconName.endsWith(".xml")) { - super.loadIcon(index, iconName, density); - return; - } - View child = getChildAt(index); - if (child instanceof ImageView) { - ImageView imageView = (ImageView) child; - // The xml is stored only in xhdpi. - IconLoader iconLoader = new IconLoader(iconName, Density.XHIGH, - mSimulatedPlatformVersion, null); - InputStream stream = iconLoader.getIcon(); - - if (stream != null) { - try { - BridgeXmlBlockParser parser = new BridgeXmlBlockParser( - ParserFactory.create(stream, null), (BridgeContext) mContext, true); - imageView.setImageDrawable( - Drawable.createFromXml(mContext.getResources(), parser)); - } catch (XmlPullParserException e) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, "Unable to draw wifi icon", e, - null); - } catch (IOException e) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, "Unable to draw wifi icon", e, - null); - } - } - } - } - - @Override - protected TextView getStyleableTextView() { - return null; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ThemePreviewNavigationBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ThemePreviewNavigationBar.java deleted file mode 100644 index 043528016c2d..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ThemePreviewNavigationBar.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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 com.android.layoutlib.bridge.bars; - -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.resources.Density; - -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.util.AttributeSet; -import android.view.View; -import android.widget.LinearLayout; - -/** - * Navigation Bar for the Theme Editor preview. - * - * For small bars, it is identical to {@link NavigationBar}. - * But wide bars from {@link NavigationBar} are too wide for the Theme Editor preview. - * To solve that problem, {@link ThemePreviewNavigationBar} use the layout for small bars, - * and have no padding on the sides. That way, they have a similar look as the true ones, - * and they fit in the Theme Editor preview. - */ -public class ThemePreviewNavigationBar extends NavigationBar { - private static final int PADDING_WIDTH_SW600 = 0; - - @SuppressWarnings("unused") - public ThemePreviewNavigationBar(Context context, AttributeSet attrs) { - super((BridgeContext) context, - Density.getEnum(((BridgeContext) context).getMetrics().densityDpi), - LinearLayout.HORIZONTAL, // In this mode, it doesn't need to be render vertically - ((BridgeContext) context).getConfiguration().getLayoutDirection() == - View.LAYOUT_DIRECTION_RTL, - (context.getApplicationInfo().flags & ApplicationInfo.FLAG_SUPPORTS_RTL) != 0, - 0, LAYOUT_XML); - } - - @Override - protected int getSidePadding(float sw) { - if (sw >= 600) { - return PADDING_WIDTH_SW600; - } - return super.getSidePadding(sw); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java deleted file mode 100644 index 4fe1001d9229..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.bars; - -import com.android.layoutlib.bridge.android.BridgeContext; - -import org.xmlpull.v1.XmlPullParserException; - -import android.widget.LinearLayout; -import android.widget.TextView; - -public class TitleBar extends CustomBar { - - private TextView mTextView; - - public TitleBar(BridgeContext context, String label, int simulatedPlatformVersion) { - super(context, LinearLayout.HORIZONTAL, "/bars/title_bar.xml", "title_bar.xml", - simulatedPlatformVersion); - - // Cannot access the inside items through id because no R.id values have been - // created for them. - // We do know the order though. - mTextView = setText(0, label, true); - - setStyle("windowTitleBackgroundStyle"); - } - - @Override - protected TextView getStyleableTextView() { - return mTextView; - } -} 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 deleted file mode 100644 index 11da44583451..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.impl; - -import com.android.layoutlib.bridge.util.Debug; -import com.android.layoutlib.bridge.util.SparseWeakArray; - -import android.annotation.Nullable; -import android.util.SparseArray; - -import java.io.PrintStream; -import java.lang.ref.WeakReference; -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.atomic.AtomicLong; - -/** - * Manages native delegates. - * - * This is used in conjunction with layoublib_create: certain Android java classes are mere - * wrappers around a heavily native based implementation, and we need a way to run these classes - * in our Android Studio rendering framework without bringing all the native code from the Android - * platform. - * - * Thus we instruct layoutlib_create to modify the bytecode of these classes to replace their - * native methods by "delegate calls". - * - * For example, a native method android.graphics.Matrix.init(...) will actually become - * a call to android.graphics.Matrix_Delegate.init(...). - * - * The Android java classes that use native code uses an int (Java side) to reference native - * objects. This int is generally directly the pointer to the C structure counterpart. - * Typically a creation method will return such an int, and then this int will be passed later - * to a Java method to identify the C object to manipulate. - * - * Since we cannot use the Java object reference as the int directly, DelegateManager manages the - * 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(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. - * - * The JNI references are counted, so we do the same through a {@link WeakReference}. Because - * 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(long)} adds and removes - * the delegate to/from a set. This set holds the reference and prevents the GC from reclaiming - * the delegate. - * - * - {@link #addNewDelegate(Object)} also adds the delegate to a {@link SparseArray} that holds a - * {@link WeakReference} to the delegate. This allows the delegate to be deleted automatically - * when nothing references it. This means that any class that holds a delegate (except for the - * Java main class) must not use the int but the Delegate class instead. The integers must - * only be used in the API between the main Java class and the Delegate. - * - * @param <T> the delegate class to manage - */ -public final class DelegateManager<T> { - @SuppressWarnings("FieldCanBeLocal") - private final Class<T> mClass; - private static final SparseWeakArray<Object> sDelegates = new SparseWeakArray<>(); - /** Set 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(long) - */ - private static final Set<Object> sJavaReferences = new HashSet<>(); - private static final AtomicLong sDelegateCounter = new AtomicLong(1); - - public DelegateManager(Class<T> theClass) { - mClass = theClass; - } - - /** - * Returns the delegate from the given native int. - * <p> - * If the int is zero, then this will always return null. - * <p> - * If the int is non zero and the delegate is not found, this will throw an assert. - * - * @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) { - Object delegate; - synchronized (DelegateManager.class) { - delegate = sDelegates.get(native_object); - } - - if (Debug.DEBUG) { - if (delegate == null) { - System.err.println("Unknown " + mClass.getSimpleName() + " with int " + - native_object); - } - } - - assert delegate != null; - //noinspection unchecked - return (T)delegate; - } - return null; - } - - /** - * Adds a delegate to the manager and returns the native int used to identify it. - * @param newDelegate the delegate to add - * @return a unique native int to identify the delegate - */ - public long addNewDelegate(T newDelegate) { - long native_object = sDelegateCounter.getAndIncrement(); - synchronized (DelegateManager.class) { - sDelegates.put(native_object, newDelegate); - // Only for development: assert !sJavaReferences.contains(newDelegate); - sJavaReferences.add(newDelegate); - } - - if (Debug.DEBUG) { - System.out.println( - "New " + mClass.getSimpleName() + " " + - "with int " + - native_object); - } - - return native_object; - } - - /** - * Removes the main reference on the given delegate. - * @param native_object the native integer representing the delegate. - */ - public void removeJavaReferenceFor(long native_object) { - synchronized (DelegateManager.class) { - T delegate = getDelegate(native_object); - - if (Debug.DEBUG) { - System.out.println("Removing main Java ref on " + mClass.getSimpleName() + - " with int " + native_object); - } - - sJavaReferences.remove(delegate); - } - } - - public synchronized static void dump(PrintStream out) { - for (Object reference : sJavaReferences) { - int idx = sDelegates.indexOfValue(reference); - out.printf("[%d] %s\n", sDelegates.keyAt(idx), reference.getClass().getSimpleName()); - } - out.printf("\nTotal number of objects: %d\n", sJavaReferences.size()); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java deleted file mode 100644 index 7526e090be50..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java +++ /dev/null @@ -1,885 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.impl; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.layoutlib.bridge.Bridge; - -import android.graphics.Bitmap_Delegate; -import android.graphics.Canvas; -import android.graphics.ColorFilter_Delegate; -import android.graphics.Paint; -import android.graphics.Paint_Delegate; -import android.graphics.PorterDuff; -import android.graphics.PorterDuff.Mode; -import android.graphics.Rect; -import android.graphics.RectF; -import android.graphics.Region; -import android.graphics.Region_Delegate; -import android.graphics.Shader_Delegate; - -import java.awt.AlphaComposite; -import java.awt.Color; -import java.awt.Composite; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.Shape; -import java.awt.geom.AffineTransform; -import java.awt.geom.Area; -import java.awt.geom.NoninvertibleTransformException; -import java.awt.geom.Rectangle2D; -import java.awt.image.BufferedImage; -import java.util.ArrayList; - -/** - * Class representing a graphics context snapshot, as well as a context stack as a linked list. - * <p> - * This is based on top of {@link Graphics2D} but can operate independently if none are available - * yet when setting transforms and clip information. - * <p> - * This allows for drawing through {@link #draw(Drawable, Paint_Delegate, boolean, boolean)} and - * {@link #draw(Drawable)} - * - * Handling of layers (created with {@link Canvas#saveLayer(RectF, Paint, int)}) is handled through - * a list of Graphics2D for each layers. The class actually maintains a list of {@link Layer} - * for each layer. Doing a save() will duplicate this list so that each graphics2D object - * ({@link Layer#getGraphics()}) is configured only for the new snapshot. - */ -public class GcSnapshot { - - private final GcSnapshot mPrevious; - private final int mFlags; - - /** list of layers. The first item in the list is always the */ - private final ArrayList<Layer> mLayers = new ArrayList<Layer>(); - - /** temp transform in case transformation are set before a Graphics2D exists */ - private AffineTransform mTransform = null; - /** temp clip in case clipping is set before a Graphics2D exists */ - private Area mClip = null; - - // local layer data - /** a local layer created with {@link Canvas#saveLayer(RectF, Paint, int)}. - * If this is null, this does not mean there's no layer, just that the snapshot is not the - * one that created the layer. - * @see #getLayerSnapshot() - */ - private final Layer mLocalLayer; - private final Paint_Delegate mLocalLayerPaint; - private final Rect mLayerBounds; - - public interface Drawable { - void draw(Graphics2D graphics, Paint_Delegate paint); - } - - /** - * Class containing information about a layer. - * - * This contains graphics, bitmap and layer information. - */ - private static class Layer { - private final Graphics2D mGraphics; - private final Bitmap_Delegate mBitmap; - private final BufferedImage mImage; - /** the flags that were used to configure the layer. This is never changed, and passed - * as is when {@link #makeCopy()} is called */ - private final int mFlags; - /** the original content of the layer when the next object was created. This is not - * passed in {@link #makeCopy()} and instead is recreated when a new layer is added - * (depending on its flags) */ - private BufferedImage mOriginalCopy; - - /** - * Creates a layer with a graphics and a bitmap. This is only used to create - * the base layer. - * - * @param graphics the graphics - * @param bitmap the bitmap - */ - Layer(Graphics2D graphics, Bitmap_Delegate bitmap) { - mGraphics = graphics; - mBitmap = bitmap; - mImage = mBitmap.getImage(); - mFlags = 0; - } - - /** - * Creates a layer with a graphics and an image. If the image belongs to a - * {@link Bitmap_Delegate} (case of the base layer), then - * {@link Layer#Layer(Graphics2D, Bitmap_Delegate)} should be used. - * - * @param graphics the graphics the new graphics for this layer - * @param image the image the image from which the graphics came - * @param flags the flags that were used to save this layer - */ - Layer(Graphics2D graphics, BufferedImage image, int flags) { - mGraphics = graphics; - mBitmap = null; - mImage = image; - mFlags = flags; - } - - /** The Graphics2D, guaranteed to be non null */ - Graphics2D getGraphics() { - return mGraphics; - } - - /** The BufferedImage, guaranteed to be non null */ - BufferedImage getImage() { - return mImage; - } - - /** Returns the layer save flags. This is only valid for additional layers. - * For the base layer this will always return 0; - * For a given layer, all further copies of this {@link Layer} object in new snapshots - * will always return the same value. - */ - int getFlags() { - return mFlags; - } - - Layer makeCopy() { - if (mBitmap != null) { - return new Layer((Graphics2D) mGraphics.create(), mBitmap); - } - - return new Layer((Graphics2D) mGraphics.create(), mImage, mFlags); - } - - /** sets an optional copy of the original content to be used during restore */ - void setOriginalCopy(BufferedImage image) { - mOriginalCopy = image; - } - - BufferedImage getOriginalCopy() { - return mOriginalCopy; - } - - void change() { - if (mBitmap != null) { - mBitmap.change(); - } - } - - /** - * Sets the clip for the graphics2D object associated with the layer. - * This should be used over the normal Graphics2D setClip method. - * - * @param clipShape the shape to use a the clip shape. - */ - void setClip(Shape clipShape) { - // because setClip is only guaranteed to work with rectangle shape, - // first reset the clip to max and then intersect the current (empty) - // clip with the shap. - mGraphics.setClip(null); - mGraphics.clip(clipShape); - } - - /** - * Clips the layer with the given shape. This performs an intersect between the current - * clip shape and the given shape. - * @param shape the new clip shape. - */ - public void clip(Shape shape) { - mGraphics.clip(shape); - } - } - - /** - * Creates the root snapshot associating it with a given bitmap. - * <p> - * If <var>bitmap</var> is null, then {@link GcSnapshot#setBitmap(Bitmap_Delegate)} must be - * called before the snapshot can be used to draw. Transform and clip operations are permitted - * before. - * - * @param bitmap the image to associate to the snapshot or null. - * @return the root snapshot - */ - public static GcSnapshot createDefaultSnapshot(Bitmap_Delegate bitmap) { - GcSnapshot snapshot = new GcSnapshot(); - if (bitmap != null) { - snapshot.setBitmap(bitmap); - } - - return snapshot; - } - - /** - * Saves the current state according to the given flags and returns the new current snapshot. - * <p/> - * This is the equivalent of {@link Canvas#save(int)} - * - * @param flags the save flags. - * @return the new snapshot - * - * @see Canvas#save(int) - */ - public GcSnapshot save(int flags) { - return new GcSnapshot(this, null /*layerbounds*/, null /*paint*/, flags); - } - - /** - * Saves the current state and creates a new layer, and returns the new current snapshot. - * <p/> - * This is the equivalent of {@link Canvas#saveLayer(RectF, Paint, int)} - * - * @param layerBounds the layer bounds - * @param paint the Paint information used to blit the layer back into the layers underneath - * upon restore - * @param flags the save flags. - * @return the new snapshot - * - * @see Canvas#saveLayer(RectF, Paint, int) - */ - public GcSnapshot saveLayer(RectF layerBounds, Paint_Delegate paint, int flags) { - return new GcSnapshot(this, layerBounds, paint, flags); - } - - /** - * Creates the root snapshot. - * {@link #setGraphics2D(Graphics2D)} will have to be called on it when possible. - */ - private GcSnapshot() { - mPrevious = null; - mFlags = 0; - mLocalLayer = null; - mLocalLayerPaint = null; - mLayerBounds = null; - } - - /** - * Creates a new {@link GcSnapshot} on top of another one, with a layer data to be restored - * into the main graphics when {@link #restore()} is called. - * - * @param previous the previous snapshot head. - * @param layerBounds the region of the layer. Optional, if null, this is a normal save() - * @param paint the Paint information used to blit the layer back into the layers underneath - * upon restore - * @param flags the flags regarding what should be saved. - */ - private GcSnapshot(GcSnapshot previous, RectF layerBounds, Paint_Delegate paint, int flags) { - assert previous != null; - mPrevious = previous; - mFlags = flags; - - // make a copy of the current layers before adding the new one. - // This keeps the same BufferedImage reference but creates new Graphics2D for this - // snapshot. - // It does not copy whatever original copy the layers have, as they will be done - // only if the new layer doesn't clip drawing to itself. - for (Layer layer : mPrevious.mLayers) { - mLayers.add(layer.makeCopy()); - } - - if (layerBounds != null) { - // get the current transform - AffineTransform matrix = mLayers.get(0).getGraphics().getTransform(); - - // transform the layerBounds with the current transform and stores it into a int rect - RectF rect2 = new RectF(); - mapRect(matrix, rect2, layerBounds); - mLayerBounds = new Rect(); - rect2.round(mLayerBounds); - - // get the base layer (always at index 0) - Layer baseLayer = mLayers.get(0); - - // create the image for the layer - BufferedImage layerImage = new BufferedImage( - baseLayer.getImage().getWidth(), - baseLayer.getImage().getHeight(), - (mFlags & Canvas.HAS_ALPHA_LAYER_SAVE_FLAG) != 0 ? - BufferedImage.TYPE_INT_ARGB : - BufferedImage.TYPE_INT_RGB); - - // create a graphics for it so that drawing can be done. - Graphics2D layerGraphics = layerImage.createGraphics(); - - // because this layer inherits the current context for transform and clip, - // set them to one from the base layer. - AffineTransform currentMtx = baseLayer.getGraphics().getTransform(); - layerGraphics.setTransform(currentMtx); - - // create a new layer for this new layer and add it to the list at the end. - mLayers.add(mLocalLayer = new Layer(layerGraphics, layerImage, flags)); - - // set the clip on it. - Shape currentClip = baseLayer.getGraphics().getClip(); - mLocalLayer.setClip(currentClip); - - // if the drawing is not clipped to the local layer only, we save the current content - // of all other layers. We are only interested in the part that will actually - // be drawn, so we create as small bitmaps as we can. - // This is so that we can erase the drawing that goes in the layers below that will - // be coming from the layer itself. - if ((mFlags & Canvas.CLIP_TO_LAYER_SAVE_FLAG) == 0) { - int w = mLayerBounds.width(); - int h = mLayerBounds.height(); - for (int i = 0 ; i < mLayers.size() - 1 ; i++) { - Layer layer = mLayers.get(i); - BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); - Graphics2D graphics = image.createGraphics(); - graphics.drawImage(layer.getImage(), - 0, 0, w, h, - mLayerBounds.left, mLayerBounds.top, - mLayerBounds.right, mLayerBounds.bottom, - null); - graphics.dispose(); - layer.setOriginalCopy(image); - } - } - } else { - mLocalLayer = null; - mLayerBounds = null; - } - - mLocalLayerPaint = paint; - } - - public void dispose() { - for (Layer layer : mLayers) { - layer.getGraphics().dispose(); - } - - if (mPrevious != null) { - mPrevious.dispose(); - } - } - - /** - * Restores the top {@link GcSnapshot}, and returns the next one. - */ - public GcSnapshot restore() { - return doRestore(); - } - - /** - * Restores the {@link GcSnapshot} to <var>saveCount</var>. - * @param saveCount the saveCount or -1 to only restore 1. - * - * @return the new head of the Gc snapshot stack. - */ - public GcSnapshot restoreTo(int saveCount) { - return doRestoreTo(size(), saveCount); - } - - public int size() { - if (mPrevious != null) { - return mPrevious.size() + 1; - } - - return 1; - } - - /** - * Link the snapshot to a Bitmap_Delegate. - * <p/> - * This is only for the case where the snapshot was created with a null image when calling - * {@link #createDefaultSnapshot(Bitmap_Delegate)}, and is therefore not yet linked to - * a previous snapshot. - * <p/> - * If any transform or clip information was set before, they are put into the Graphics object. - * @param bitmap the bitmap to link to. - */ - public void setBitmap(Bitmap_Delegate bitmap) { - // create a new Layer for the bitmap. This will be the base layer. - Graphics2D graphics2D = bitmap.getImage().createGraphics(); - Layer baseLayer = new Layer(graphics2D, bitmap); - - // Set the current transform and clip which can either come from mTransform/mClip if they - // were set when there was no bitmap/layers or from the current base layers if there is - // one already. - - graphics2D.setTransform(getTransform()); - // reset mTransform in case there was one. - mTransform = null; - - baseLayer.setClip(getClip()); - // reset mClip in case there was one. - mClip = null; - - // replace whatever current layers we have with this. - mLayers.clear(); - mLayers.add(baseLayer); - - } - - public void translate(float dx, float dy) { - if (mLayers.size() > 0) { - for (Layer layer : mLayers) { - layer.getGraphics().translate(dx, dy); - } - } else { - if (mTransform == null) { - mTransform = new AffineTransform(); - } - mTransform.translate(dx, dy); - } - } - - public void rotate(double radians) { - if (mLayers.size() > 0) { - for (Layer layer : mLayers) { - layer.getGraphics().rotate(radians); - } - } else { - if (mTransform == null) { - mTransform = new AffineTransform(); - } - mTransform.rotate(radians); - } - } - - public void scale(float sx, float sy) { - if (mLayers.size() > 0) { - for (Layer layer : mLayers) { - layer.getGraphics().scale(sx, sy); - } - } else { - if (mTransform == null) { - mTransform = new AffineTransform(); - } - mTransform.scale(sx, sy); - } - } - - public AffineTransform getTransform() { - if (mLayers.size() > 0) { - // all graphics2D in the list have the same transform - return mLayers.get(0).getGraphics().getTransform(); - } else { - if (mTransform == null) { - mTransform = new AffineTransform(); - } - return mTransform; - } - } - - public void setTransform(AffineTransform transform) { - if (mLayers.size() > 0) { - for (Layer layer : mLayers) { - layer.getGraphics().setTransform(transform); - } - } else { - if (mTransform == null) { - mTransform = new AffineTransform(); - } - mTransform.setTransform(transform); - } - } - - public boolean clip(Shape shape, int regionOp) { - // Simple case of intersect with existing layers. - // Because Graphics2D#setClip works a bit peculiarly, we optimize - // the case of clipping by intersection, as it's supported natively. - if (regionOp == Region.Op.INTERSECT.nativeInt && mLayers.size() > 0) { - for (Layer layer : mLayers) { - layer.clip(shape); - } - - Shape currentClip = getClip(); - return currentClip != null && currentClip.getBounds().isEmpty() == false; - } - - Area area = null; - - if (regionOp == Region.Op.REPLACE.nativeInt) { - area = new Area(shape); - } else { - area = Region_Delegate.combineShapes(getClip(), shape, regionOp); - } - - assert area != null; - - if (mLayers.size() > 0) { - if (area != null) { - for (Layer layer : mLayers) { - layer.setClip(area); - } - } - - Shape currentClip = getClip(); - return currentClip != null && currentClip.getBounds().isEmpty() == false; - } else { - if (area != null) { - mClip = area; - } else { - mClip = new Area(); - } - - return mClip.getBounds().isEmpty() == false; - } - } - - public boolean clipRect(float left, float top, float right, float bottom, int regionOp) { - return clip(new Rectangle2D.Float(left, top, right - left, bottom - top), regionOp); - } - - /** - * Returns the current clip, or null if none have been setup. - */ - public Shape getClip() { - if (mLayers.size() > 0) { - // they all have the same clip - return mLayers.get(0).getGraphics().getClip(); - } else { - return mClip; - } - } - - private GcSnapshot doRestoreTo(int size, int saveCount) { - if (size <= saveCount) { - return this; - } - - // restore the current one first. - GcSnapshot previous = doRestore(); - - if (size == saveCount + 1) { // this was the only one that needed restore. - return previous; - } else { - return previous.doRestoreTo(size - 1, saveCount); - } - } - - /** - * Executes the Drawable's draw method, with a null paint delegate. - * <p/> - * Note that the method can be called several times if there are more than one active layer. - */ - public void draw(Drawable drawable) { - draw(drawable, null, false /*compositeOnly*/, false /*forceSrcMode*/); - } - - /** - * Executes the Drawable's draw method. - * <p/> - * Note that the method can be called several times if there are more than one active layer. - * @param compositeOnly whether the paint is used for composite only. This is typically - * the case for bitmaps. - * @param forceSrcMode if true, this overrides the composite to be SRC - */ - public void draw(Drawable drawable, Paint_Delegate paint, boolean compositeOnly, - boolean forceSrcMode) { - int forceMode = forceSrcMode ? AlphaComposite.SRC : 0; - // the current snapshot may not have a mLocalLayer (ie it was created on save() instead - // of saveLayer(), but that doesn't mean there's no layer. - // mLayers however saves all the information we need (flags). - if (mLayers.size() == 1) { - // no layer, only base layer. easy case. - drawInLayer(mLayers.get(0), drawable, paint, compositeOnly, forceMode); - } else { - // draw in all the layers until the layer save flags tells us to stop (ie drawing - // in that layer is limited to the layer itself. - int flags; - int i = mLayers.size() - 1; - - do { - Layer layer = mLayers.get(i); - - drawInLayer(layer, drawable, paint, compositeOnly, forceMode); - - // then go to previous layer, only if there are any left, and its flags - // doesn't restrict drawing to the layer itself. - i--; - flags = layer.getFlags(); - } while (i >= 0 && (flags & Canvas.CLIP_TO_LAYER_SAVE_FLAG) == 0); - } - } - - private void drawInLayer(Layer layer, Drawable drawable, Paint_Delegate paint, - boolean compositeOnly, int forceMode) { - Graphics2D originalGraphics = layer.getGraphics(); - if (paint == null) { - drawOnGraphics((Graphics2D) originalGraphics.create(), drawable, - null /*paint*/, layer); - } else { - ColorFilter_Delegate filter = paint.getColorFilter(); - if (filter == null || !filter.isSupported()) { - // get a Graphics2D object configured with the drawing parameters. - Graphics2D configuredGraphics = createCustomGraphics(originalGraphics, paint, - compositeOnly, forceMode); - drawOnGraphics(configuredGraphics, drawable, paint, layer); - return; - } - - int x = 0; - int y = 0; - int width; - int height; - Rectangle clipBounds = originalGraphics.getClip() != null ? originalGraphics - .getClipBounds() : null; - if (clipBounds != null) { - if (clipBounds.width == 0 || clipBounds.height == 0) { - // Clip is 0 so no need to paint anything. - return; - } - // If we have clipBounds available, use them as they will always be - // smaller than the full layer size. - x = clipBounds.x; - y = clipBounds.y; - width = clipBounds.width; - height = clipBounds.height; - } else { - width = layer.getImage().getWidth(); - height = layer.getImage().getHeight(); - } - - // Create a temporary image to which the color filter will be applied. - BufferedImage image = new BufferedImage(width, height, - BufferedImage.TYPE_INT_ARGB); - Graphics2D imageBaseGraphics = (Graphics2D) image.getGraphics(); - // Configure the Graphics2D object with drawing parameters and shader. - Graphics2D imageGraphics = createCustomGraphics( - imageBaseGraphics, paint, compositeOnly, - AlphaComposite.SRC_OVER); - // get a Graphics2D object configured with the drawing parameters, but no shader. - Graphics2D configuredGraphics = createCustomGraphics(originalGraphics, paint, - true /*compositeOnly*/, forceMode); - try { - // The main draw operation. - // We translate the operation to take into account that the rendering does not - // know about the clipping area. - imageGraphics.translate(-x, -y); - drawable.draw(imageGraphics, paint); - - // Apply the color filter. - // Restore the original coordinates system and apply the filter only to the - // clipped area. - imageGraphics.translate(x, y); - filter.applyFilter(imageGraphics, width, height); - - // Draw the tinted image on the main layer using as start point the clipping - // upper left coordinates. - configuredGraphics.drawImage(image, x, y, null); - layer.change(); - } finally { - // dispose Graphics2D objects - imageGraphics.dispose(); - imageBaseGraphics.dispose(); - configuredGraphics.dispose(); - } - } - } - - private void drawOnGraphics(Graphics2D g, Drawable drawable, Paint_Delegate paint, - Layer layer) { - try { - drawable.draw(g, paint); - layer.change(); - } finally { - g.dispose(); - } - } - - private GcSnapshot doRestore() { - if (mPrevious != null) { - if (mLocalLayer != null) { - // prepare to blit the layers in which we have draw, in the layer beneath - // them, starting with the top one (which is the current local layer). - int i = mLayers.size() - 1; - int flags; - do { - Layer dstLayer = mLayers.get(i - 1); - - restoreLayer(dstLayer); - - flags = dstLayer.getFlags(); - i--; - } while (i > 0 && (flags & Canvas.CLIP_TO_LAYER_SAVE_FLAG) == 0); - } - - // if this snapshot does not save everything, then set the previous snapshot - // to this snapshot content - - // didn't save the matrix? set the current matrix on the previous snapshot - if ((mFlags & Canvas.MATRIX_SAVE_FLAG) == 0) { - AffineTransform mtx = getTransform(); - for (Layer layer : mPrevious.mLayers) { - layer.getGraphics().setTransform(mtx); - } - } - - // didn't save the clip? set the current clip on the previous snapshot - if ((mFlags & Canvas.CLIP_SAVE_FLAG) == 0) { - Shape clip = getClip(); - for (Layer layer : mPrevious.mLayers) { - layer.setClip(clip); - } - } - } - - for (Layer layer : mLayers) { - layer.getGraphics().dispose(); - } - - return mPrevious; - } - - private void restoreLayer(Layer dstLayer) { - - Graphics2D baseGfx = dstLayer.getImage().createGraphics(); - - // if the layer contains an original copy this means the flags - // didn't restrict drawing to the local layer and we need to make sure the - // layer bounds in the layer beneath didn't receive any drawing. - // so we use the originalCopy to erase the new drawings in there. - BufferedImage originalCopy = dstLayer.getOriginalCopy(); - if (originalCopy != null) { - Graphics2D g = (Graphics2D) baseGfx.create(); - g.setComposite(AlphaComposite.Src); - - g.drawImage(originalCopy, - mLayerBounds.left, mLayerBounds.top, mLayerBounds.right, mLayerBounds.bottom, - 0, 0, mLayerBounds.width(), mLayerBounds.height(), - null); - g.dispose(); - } - - // now draw put the content of the local layer onto the layer, - // using the paint information - Graphics2D g = createCustomGraphics(baseGfx, mLocalLayerPaint, - true /*alphaOnly*/, 0 /*forceMode*/); - - g.drawImage(mLocalLayer.getImage(), - mLayerBounds.left, mLayerBounds.top, mLayerBounds.right, mLayerBounds.bottom, - mLayerBounds.left, mLayerBounds.top, mLayerBounds.right, mLayerBounds.bottom, - null); - g.dispose(); - - baseGfx.dispose(); - } - - /** - * Creates a new {@link Graphics2D} based on the {@link Paint} parameters. - * <p/>The object must be disposed ({@link Graphics2D#dispose()}) after being used. - */ - private Graphics2D createCustomGraphics(Graphics2D original, Paint_Delegate paint, - boolean compositeOnly, int forceMode) { - // make new one graphics - Graphics2D g = (Graphics2D) original.create(); - - // configure it - - if (paint.isAntiAliased()) { - g.setRenderingHint( - RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g.setRenderingHint( - RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); - } - - // set the shader first, as it'll replace the color if it can be used it. - boolean customShader = false; - if (!compositeOnly) { - customShader = setShader(g, paint); - // set the stroke - g.setStroke(paint.getJavaStroke()); - } - // set the composite. - setComposite(g, paint, compositeOnly || customShader, forceMode); - - return g; - } - - private boolean setShader(Graphics2D g, Paint_Delegate paint) { - Shader_Delegate shaderDelegate = paint.getShader(); - if (shaderDelegate != null) { - if (shaderDelegate.isSupported()) { - java.awt.Paint shaderPaint = shaderDelegate.getJavaPaint(); - assert shaderPaint != null; - if (shaderPaint != null) { - g.setPaint(shaderPaint); - return true; - } - } else { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_SHADER, - shaderDelegate.getSupportMessage(), - null /*throwable*/, null /*data*/); - } - } - - // if no shader, use the paint color - g.setColor(new Color(paint.getColor(), true /*hasAlpha*/)); - - return false; - } - - private void setComposite(Graphics2D g, Paint_Delegate paint, boolean usePaintAlpha, - int forceMode) { - // the alpha for the composite. Always opaque if the normal paint color is used since - // it contains the alpha - int alpha = usePaintAlpha ? paint.getAlpha() : 0xFF; - if (forceMode != 0) { - g.setComposite(AlphaComposite.getInstance(forceMode, (float) alpha / 255.f)); - return; - } - Mode mode = PorterDuff.intToMode(paint.getPorterDuffMode()); - Composite composite = PorterDuffUtility.getComposite(mode, alpha); - g.setComposite(composite); - } - - private void mapRect(AffineTransform matrix, RectF dst, RectF src) { - // array with 4 corners - float[] corners = new float[] { - src.left, src.top, - src.right, src.top, - src.right, src.bottom, - src.left, src.bottom, - }; - - // apply the transform to them. - matrix.transform(corners, 0, corners, 0, 4); - - // now put the result in the rect. We take the min/max of Xs and min/max of Ys - dst.left = Math.min(Math.min(corners[0], corners[2]), Math.min(corners[4], corners[6])); - dst.right = Math.max(Math.max(corners[0], corners[2]), Math.max(corners[4], corners[6])); - - dst.top = Math.min(Math.min(corners[1], corners[3]), Math.min(corners[5], corners[7])); - dst.bottom = Math.max(Math.max(corners[1], corners[3]), Math.max(corners[5], corners[7])); - } - - /** - * Returns the clip of the oldest snapshot of the stack, appropriately translated to be - * expressed in the coordinate system of the latest snapshot. - */ - public Rectangle getOriginalClip() { - GcSnapshot originalSnapshot = this; - while (originalSnapshot.mPrevious != null) { - originalSnapshot = originalSnapshot.mPrevious; - } - if (originalSnapshot.mLayers.isEmpty()) { - return null; - } - Graphics2D graphics2D = originalSnapshot.mLayers.get(0).getGraphics(); - Rectangle bounds = graphics2D.getClipBounds(); - if (bounds == null) { - return null; - } - try { - AffineTransform originalTransform = - ((Graphics2D) graphics2D.create()).getTransform().createInverse(); - AffineTransform latestTransform = getTransform().createInverse(); - bounds.x += latestTransform.getTranslateX() - originalTransform.getTranslateX(); - bounds.y += latestTransform.getTranslateY() - originalTransform.getTranslateY(); - } catch (NoninvertibleTransformException e) { - Bridge.getLog().warning(null, "Non invertible transformation", null); - } - return bounds; - } - -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java deleted file mode 100644 index 287334c2fc8b..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java +++ /dev/null @@ -1,467 +0,0 @@ -/* - * 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 com.android.layoutlib.bridge.impl; - -import com.android.ide.common.rendering.api.HardwareConfig; -import com.android.ide.common.rendering.api.RenderResources; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.rendering.api.SessionParams; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.android.RenderParamsFlags; -import com.android.layoutlib.bridge.bars.AppCompatActionBar; -import com.android.layoutlib.bridge.bars.BridgeActionBar; -import com.android.layoutlib.bridge.bars.Config; -import com.android.layoutlib.bridge.bars.FrameworkActionBar; -import com.android.layoutlib.bridge.bars.NavigationBar; -import com.android.layoutlib.bridge.bars.StatusBar; -import com.android.layoutlib.bridge.bars.TitleBar; -import com.android.resources.Density; -import com.android.resources.ResourceType; -import com.android.resources.ScreenOrientation; - -import android.annotation.NonNull; -import android.graphics.drawable.Drawable; -import android.util.DisplayMetrics; -import android.util.TypedValue; -import android.view.AttachInfo_Accessor; -import android.view.View; -import android.view.ViewRootImpl; -import android.view.ViewRootImpl_Accessor; -import android.widget.FrameLayout; -import android.widget.LinearLayout; -import android.widget.RelativeLayout; - -import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; -import static android.widget.LinearLayout.VERTICAL; -import static com.android.layoutlib.bridge.impl.ResourceHelper.getBooleanThemeValue; - -/** - * The Layout used to create the system decor. - * - * The layout inflated will contain a content frame where the user's layout can be inflated. - * <pre> - * +-------------------------------------------------+---+ - * | Status bar | N | - * +-------------------------------------------------+ a | - * | Title/Action bar (optional) | v | - * +-------------------------------------------------+ | - * | Content, vertical extending | b | - * | | a | - * | | r | - * +-------------------------------------------------+---+ - * </pre> - * or - * <pre> - * +-------------------------------------+ - * | Status bar | - * +-------------------------------------+ - * | Title/Action bar (optional) | - * +-------------------------------------+ - * | Content, vertical extending | - * | | - * | | - * +-------------------------------------+ - * | Nav bar | - * +-------------------------------------+ - * </pre> - * - */ -class Layout extends RelativeLayout { - - // Theme attributes used for configuring appearance of the system decor. - private static final String ATTR_WINDOW_FLOATING = "windowIsFloating"; - private static final String ATTR_WINDOW_BACKGROUND = "windowBackground"; - private static final String ATTR_WINDOW_FULL_SCREEN = "windowFullscreen"; - private static final String ATTR_NAV_BAR_HEIGHT = "navigation_bar_height"; - private static final String ATTR_NAV_BAR_WIDTH = "navigation_bar_width"; - private static final String ATTR_STATUS_BAR_HEIGHT = "status_bar_height"; - private static final String ATTR_WINDOW_ACTION_BAR = "windowActionBar"; - private static final String ATTR_ACTION_BAR_SIZE = "actionBarSize"; - private static final String ATTR_WINDOW_NO_TITLE = "windowNoTitle"; - private static final String ATTR_WINDOW_TITLE_SIZE = "windowTitleSize"; - private static final String ATTR_WINDOW_TRANSLUCENT_STATUS = StatusBar.ATTR_TRANSLUCENT; - private static final String ATTR_WINDOW_TRANSLUCENT_NAV = NavigationBar.ATTR_TRANSLUCENT; - - // Default sizes - private static final int DEFAULT_STATUS_BAR_HEIGHT = 25; - private static final int DEFAULT_TITLE_BAR_HEIGHT = 25; - private static final int DEFAULT_NAV_BAR_SIZE = 48; - - // Ids assigned to components created. This is so that we can refer to other components in - // layout params. - private static final String ID_NAV_BAR = "navBar"; - private static final String ID_STATUS_BAR = "statusBar"; - private static final String ID_TITLE_BAR = "titleBar"; - // Prefix used with the above ids in order to make them unique in framework namespace. - private static final String ID_PREFIX = "android_layoutlib_"; - - /** - * Temporarily store the builder so that it doesn't have to be passed to all methods used - * during inflation. - */ - private Builder mBuilder; - - /** - * This holds user's layout. - */ - private FrameLayout mContentRoot; - - public Layout(@NonNull Builder builder) { - super(builder.mContext); - mBuilder = builder; - if (builder.mWindowBackground != null) { - Drawable d = ResourceHelper.getDrawable(builder.mWindowBackground, builder.mContext); - setBackground(d); - } - - int simulatedPlatformVersion = getParams().getSimulatedPlatformVersion(); - HardwareConfig hwConfig = getParams().getHardwareConfig(); - Density density = hwConfig.getDensity(); - boolean isRtl = Bridge.isLocaleRtl(getParams().getLocale()); - setLayoutDirection(isRtl? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR); - - NavigationBar navBar = null; - if (mBuilder.hasNavBar()) { - navBar = createNavBar(getContext(), density, isRtl, getParams().isRtlSupported(), - simulatedPlatformVersion); - } - - StatusBar statusBar = null; - if (builder.mStatusBarSize > 0) { - statusBar = createStatusBar(getContext(), density, isRtl, getParams().isRtlSupported(), - simulatedPlatformVersion); - } - - View actionBar = null; - TitleBar titleBar = null; - if (builder.mActionBarSize > 0) { - BridgeActionBar bar = createActionBar(getContext(), getParams()); - mContentRoot = bar.getContentRoot(); - actionBar = bar.getRootView(); - } else if (mBuilder.mTitleBarSize > 0) { - titleBar = createTitleBar(getContext(), getParams().getAppLabel(), - simulatedPlatformVersion); - } - - addViews(titleBar, mContentRoot == null ? (mContentRoot = createContentFrame()) : actionBar, - statusBar, navBar); - // Done with the builder. Don't hold a reference to it. - mBuilder = null; - } - - @NonNull - private FrameLayout createContentFrame() { - FrameLayout contentRoot = new FrameLayout(getContext()); - LayoutParams params = createLayoutParams(MATCH_PARENT, MATCH_PARENT); - int rule = mBuilder.isNavBarVertical() ? START_OF : ABOVE; - if (mBuilder.hasSolidNavBar()) { - params.addRule(rule, getId(ID_NAV_BAR)); - } - int below = -1; - if (mBuilder.mActionBarSize <= 0 && mBuilder.mTitleBarSize > 0) { - below = getId(ID_TITLE_BAR); - } else if (mBuilder.hasSolidStatusBar()) { - below = getId(ID_STATUS_BAR); - } - if (below != -1) { - params.addRule(BELOW, below); - } - contentRoot.setLayoutParams(params); - return contentRoot; - } - - @NonNull - private LayoutParams createLayoutParams(int width, int height) { - DisplayMetrics metrics = getContext().getResources().getDisplayMetrics(); - if (width > 0) { - width = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, width, metrics); - } - if (height > 0) { - height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, height, metrics); - } - return new LayoutParams(width, height); - } - - @NonNull - public FrameLayout getContentRoot() { - return mContentRoot; - } - - @NonNull - private SessionParams getParams() { - return mBuilder.mParams; - } - - @NonNull - @Override - public BridgeContext getContext(){ - return (BridgeContext) super.getContext(); - } - - /** - * @param isRtl whether the current locale is an RTL locale. - * @param isRtlSupported whether the applications supports RTL (i.e. has supportsRtl=true - * in the manifest and targetSdkVersion >= 17. - */ - @NonNull - private StatusBar createStatusBar(BridgeContext context, Density density, boolean isRtl, - boolean isRtlSupported, int simulatedPlatformVersion) { - StatusBar statusBar = - new StatusBar(context, density, isRtl, isRtlSupported, simulatedPlatformVersion); - LayoutParams params = createLayoutParams(MATCH_PARENT, mBuilder.mStatusBarSize); - if (mBuilder.isNavBarVertical()) { - params.addRule(START_OF, getId(ID_NAV_BAR)); - } - statusBar.setLayoutParams(params); - statusBar.setId(getId(ID_STATUS_BAR)); - return statusBar; - } - - private BridgeActionBar createActionBar(@NonNull BridgeContext context, - @NonNull SessionParams params) { - boolean isMenu = "menu".equals(params.getFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG)); - - BridgeActionBar actionBar; - if (context.isAppCompatTheme() && !isMenu) { - actionBar = new AppCompatActionBar(context, params); - } else { - actionBar = new FrameworkActionBar(context, params); - } - LayoutParams layoutParams = createLayoutParams(MATCH_PARENT, MATCH_PARENT); - int rule = mBuilder.isNavBarVertical() ? START_OF : ABOVE; - if (mBuilder.hasSolidNavBar()) { - layoutParams.addRule(rule, getId(ID_NAV_BAR)); - } - if (mBuilder.hasSolidStatusBar()) { - layoutParams.addRule(BELOW, getId(ID_STATUS_BAR)); - } - actionBar.getRootView().setLayoutParams(layoutParams); - actionBar.createMenuPopup(); - return actionBar; - } - - @NonNull - private TitleBar createTitleBar(BridgeContext context, String title, - int simulatedPlatformVersion) { - TitleBar titleBar = new TitleBar(context, title, simulatedPlatformVersion); - LayoutParams params = createLayoutParams(MATCH_PARENT, mBuilder.mTitleBarSize); - if (mBuilder.hasSolidStatusBar()) { - params.addRule(BELOW, getId(ID_STATUS_BAR)); - } - if (mBuilder.isNavBarVertical() && mBuilder.hasSolidNavBar()) { - params.addRule(START_OF, getId(ID_NAV_BAR)); - } - titleBar.setLayoutParams(params); - titleBar.setId(getId(ID_TITLE_BAR)); - return titleBar; - } - - /** - * @param isRtl whether the current locale is an RTL locale. - * @param isRtlSupported whether the applications supports RTL (i.e. has supportsRtl=true - * in the manifest and targetSdkVersion >= 17. - */ - @NonNull - private NavigationBar createNavBar(BridgeContext context, Density density, boolean isRtl, - boolean isRtlSupported, int simulatedPlatformVersion) { - int orientation = mBuilder.mNavBarOrientation; - int size = mBuilder.mNavBarSize; - NavigationBar navBar = new NavigationBar(context, density, orientation, isRtl, - isRtlSupported, simulatedPlatformVersion); - boolean isVertical = mBuilder.isNavBarVertical(); - int w = isVertical ? size : MATCH_PARENT; - int h = isVertical ? MATCH_PARENT : size; - LayoutParams params = createLayoutParams(w, h); - params.addRule(isVertical ? ALIGN_PARENT_END : ALIGN_PARENT_BOTTOM); - navBar.setLayoutParams(params); - navBar.setId(getId(ID_NAV_BAR)); - return navBar; - } - - private void addViews(@NonNull View... views) { - for (View view : views) { - if (view != null) { - addView(view); - } - } - } - - private int getId(String name) { - return Bridge.getResourceId(ResourceType.ID, ID_PREFIX + name); - } - - @SuppressWarnings("deprecation") - @Override - public void requestFitSystemWindows() { - // The framework call would usually bubble up to ViewRootImpl but, in layoutlib, Layout will - // act as view root for most purposes. That way, we can also save going through the Handler - // to dispatch the new applied insets. - ViewRootImpl root = AttachInfo_Accessor.getRootView(this); - if (root != null) { - ViewRootImpl_Accessor.dispatchApplyInsets(root, this); - } - } - - /** - * A helper class to help initialize the Layout. - */ - static class Builder { - @NonNull - private final SessionParams mParams; - @NonNull - private final BridgeContext mContext; - private final RenderResources mResources; - - private final boolean mWindowIsFloating; - private ResourceValue mWindowBackground; - private int mStatusBarSize; - private int mNavBarSize; - private int mNavBarOrientation; - private int mActionBarSize; - private int mTitleBarSize; - private boolean mTranslucentStatus; - private boolean mTranslucentNav; - - public Builder(@NonNull SessionParams params, @NonNull BridgeContext context) { - mParams = params; - mContext = context; - mResources = mParams.getResources(); - mWindowIsFloating = getBooleanThemeValue(mResources, ATTR_WINDOW_FLOATING, true, true); - - findBackground(); - - if (!mParams.isForceNoDecor()) { - findStatusBar(); - findActionBar(); - findNavBar(); - } - } - - private void findBackground() { - if (!mParams.isBgColorOverridden()) { - mWindowBackground = mResources.findItemInTheme(ATTR_WINDOW_BACKGROUND, true); - mWindowBackground = mResources.resolveResValue(mWindowBackground); - } - } - - private void findStatusBar() { - boolean windowFullScreen = - getBooleanThemeValue(mResources, ATTR_WINDOW_FULL_SCREEN, true, false); - if (!windowFullScreen && !mWindowIsFloating) { - mStatusBarSize = - getDimension(ATTR_STATUS_BAR_HEIGHT, true, DEFAULT_STATUS_BAR_HEIGHT); - mTranslucentStatus = getBooleanThemeValue(mResources, - ATTR_WINDOW_TRANSLUCENT_STATUS, true, false); - } - } - - private void findActionBar() { - if (mWindowIsFloating) { - return; - } - // Check if an actionbar is needed - boolean isMenu = "menu".equals(mParams.getFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG)); - boolean windowActionBar = isMenu || - getBooleanThemeValue(mResources, ATTR_WINDOW_ACTION_BAR, - !mContext.isAppCompatTheme(), true); - if (windowActionBar) { - mActionBarSize = getDimension(ATTR_ACTION_BAR_SIZE, true, DEFAULT_TITLE_BAR_HEIGHT); - } else { - // Maybe the gingerbread era title bar is needed - boolean windowNoTitle = - getBooleanThemeValue(mResources, ATTR_WINDOW_NO_TITLE, true, false); - if (!windowNoTitle) { - mTitleBarSize = - getDimension(ATTR_WINDOW_TITLE_SIZE, true, DEFAULT_TITLE_BAR_HEIGHT); - } - } - } - - private void findNavBar() { - if (hasSoftwareButtons() && !mWindowIsFloating) { - - // get orientation - HardwareConfig hwConfig = mParams.getHardwareConfig(); - boolean barOnBottom = true; - - if (hwConfig.getOrientation() == ScreenOrientation.LANDSCAPE) { - int shortSize = hwConfig.getScreenHeight(); - int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / - hwConfig.getDensity().getDpiValue(); - - // 0-599dp: "phone" UI with bar on the side - // 600+dp: "tablet" UI with bar on the bottom - barOnBottom = shortSizeDp >= 600; - } - - mNavBarOrientation = barOnBottom ? LinearLayout.HORIZONTAL : VERTICAL; - mNavBarSize = getDimension(barOnBottom ? ATTR_NAV_BAR_HEIGHT : ATTR_NAV_BAR_WIDTH, - true, DEFAULT_NAV_BAR_SIZE); - mTranslucentNav = getBooleanThemeValue(mResources, - ATTR_WINDOW_TRANSLUCENT_NAV, true, false); - } - } - - @SuppressWarnings("SameParameterValue") - private int getDimension(String attr, boolean isFramework, int defaultValue) { - ResourceValue value = mResources.findItemInTheme(attr, isFramework); - value = mResources.resolveResValue(value); - if (value != null) { - TypedValue typedValue = ResourceHelper.getValue(attr, value.getValue(), true); - if (typedValue != null) { - return (int) typedValue.getDimension(mContext.getMetrics()); - } - } - return defaultValue; - } - - private boolean hasSoftwareButtons() { - return mParams.getHardwareConfig().hasSoftwareButtons(); - } - - /** - * Return true if the nav bar is present and not translucent - */ - private boolean hasSolidNavBar() { - return hasNavBar() && !mTranslucentNav; - } - - /** - * Return true if the status bar is present and not translucent - */ - private boolean hasSolidStatusBar() { - return hasStatusBar() && !mTranslucentStatus; - } - - private boolean hasNavBar() { - return Config.showOnScreenNavBar(mParams.getSimulatedPlatformVersion()) && - hasSoftwareButtons() && mNavBarSize > 0; - } - - private boolean hasStatusBar() { - return mStatusBarSize > 0; - } - - /** - * Return true if the nav bar is present and is vertical. - */ - private boolean isNavBarVertical() { - return hasNavBar() && mNavBarOrientation == VERTICAL; - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutParserWrapper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutParserWrapper.java deleted file mode 100644 index 71e7fd2c5eea..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutParserWrapper.java +++ /dev/null @@ -1,377 +0,0 @@ -/* - * 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 com.android.layoutlib.bridge.impl; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import android.annotation.Nullable; - -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * A wrapper around XmlPullParser that can peek forward to inspect if the file is a data-binding - * layout and some parts need to be stripped. - */ -public class LayoutParserWrapper implements XmlPullParser { - - // Data binding constants. - private static final String TAG_LAYOUT = "layout"; - private static final String TAG_DATA = "data"; - private static final String DEFAULT = "default="; - - private final XmlPullParser mDelegate; - - // Storage for peeked values. - private boolean mPeeked; - private int mEventType; - private int mDepth; - private int mNext; - private List<Attribute> mAttributes; - private String mText; - private String mName; - - // Used to end the document before the actual parser ends. - private int mFinalDepth = -1; - private boolean mEndNow; - - public LayoutParserWrapper(XmlPullParser delegate) { - mDelegate = delegate; - } - - public LayoutParserWrapper peekTillLayoutStart() throws IOException, XmlPullParserException { - final int STATE_LAYOUT_NOT_STARTED = 0; // <layout> tag not encountered yet. - final int STATE_ROOT_NOT_STARTED = 1; // the main view root not found yet. - final int STATE_INSIDE_DATA = 2; // START_TAG for <data> found, but not END_TAG. - - int state = STATE_LAYOUT_NOT_STARTED; - int dataDepth = -1; // depth of the <data> tag. Should be two. - while (true) { - int peekNext = peekNext(); - switch (peekNext) { - case START_TAG: - if (state == STATE_LAYOUT_NOT_STARTED) { - if (mName.equals(TAG_LAYOUT)) { - state = STATE_ROOT_NOT_STARTED; - } else { - return this; // no layout tag in the file. - } - } else if (state == STATE_ROOT_NOT_STARTED) { - if (mName.equals(TAG_DATA)) { - state = STATE_INSIDE_DATA; - dataDepth = mDepth; - } else { - mFinalDepth = mDepth; - return this; - } - } - break; - case END_TAG: - if (state == STATE_INSIDE_DATA) { - if (mDepth <= dataDepth) { - state = STATE_ROOT_NOT_STARTED; - } - } - break; - case END_DOCUMENT: - // No layout start found. - return this; - } - // consume the peeked tag. - next(); - } - } - - private int peekNext() throws IOException, XmlPullParserException { - if (mPeeked) { - return mNext; - } - mEventType = mDelegate.getEventType(); - mNext = mDelegate.next(); - if (mEventType == START_TAG) { - int count = mDelegate.getAttributeCount(); - mAttributes = count > 0 ? new ArrayList<Attribute>(count) : - Collections.<Attribute>emptyList(); - for (int i = 0; i < count; i++) { - mAttributes.add(new Attribute(mDelegate.getAttributeNamespace(i), - mDelegate.getAttributeName(i), mDelegate.getAttributeValue(i))); - } - } - mDepth = mDelegate.getDepth(); - mText = mDelegate.getText(); - mName = mDelegate.getName(); - mPeeked = true; - return mNext; - } - - private void reset() { - mAttributes = null; - mText = null; - mName = null; - mPeeked = false; - } - - @Override - public int next() throws XmlPullParserException, IOException { - int returnValue; - int depth; - if (mPeeked) { - returnValue = mNext; - depth = mDepth; - reset(); - } else if (mEndNow) { - return END_DOCUMENT; - } else { - returnValue = mDelegate.next(); - depth = getDepth(); - } - if (returnValue == END_TAG && depth <= mFinalDepth) { - mEndNow = true; - } - return returnValue; - } - - @Override - public int getEventType() throws XmlPullParserException { - return mPeeked ? mEventType : mDelegate.getEventType(); - } - - @Override - public int getDepth() { - return mPeeked ? mDepth : mDelegate.getDepth(); - } - - @Override - public String getName() { - return mPeeked ? mName : mDelegate.getName(); - } - - @Override - public String getText() { - return mPeeked ? mText : mDelegate.getText(); - } - - @Override - public String getAttributeValue(@Nullable String namespace, String name) { - String returnValue = null; - if (mPeeked) { - if (mAttributes == null) { - if (mEventType != START_TAG) { - throw new IndexOutOfBoundsException("getAttributeValue() called when not at START_TAG."); - } else { - return null; - } - } else { - for (Attribute attribute : mAttributes) { - //noinspection StringEquality for nullness check. - if (attribute.name.equals(name) && (attribute.namespace == namespace || - attribute.namespace != null && attribute.namespace.equals(namespace))) { - returnValue = attribute.value; - break; - } - } - } - } else { - returnValue = mDelegate.getAttributeValue(namespace, name); - } - // Check if the value is bound via data-binding, if yes get the default value. - if (returnValue != null && mFinalDepth >= 0 && returnValue.startsWith("@{")) { - // TODO: Improve the detection of default keyword. - int i = returnValue.lastIndexOf(DEFAULT); - return i > 0 ? returnValue.substring(i + DEFAULT.length(), returnValue.length() - 1) - : null; - } - return returnValue; - } - - private static class Attribute { - @Nullable - public final String namespace; - public final String name; - public final String value; - - public Attribute(@Nullable String namespace, String name, String value) { - this.namespace = namespace; - this.name = name; - this.value = value; - } - } - - // Not affected by peeking. - - @Override - public void setFeature(String s, boolean b) throws XmlPullParserException { - mDelegate.setFeature(s, b); - } - - @Override - public void setProperty(String s, Object o) throws XmlPullParserException { - mDelegate.setProperty(s, o); - } - - @Override - public void setInput(InputStream inputStream, String s) throws XmlPullParserException { - mDelegate.setInput(inputStream, s); - } - - @Override - public void setInput(Reader reader) throws XmlPullParserException { - mDelegate.setInput(reader); - } - - @Override - public String getInputEncoding() { - return mDelegate.getInputEncoding(); - } - - @Override - public String getNamespace(String s) { - return mDelegate.getNamespace(s); - } - - @Override - public String getPositionDescription() { - return mDelegate.getPositionDescription(); - } - - @Override - public int getLineNumber() { - return mDelegate.getLineNumber(); - } - - @Override - public String getNamespace() { - return mDelegate.getNamespace(); - } - - @Override - public int getColumnNumber() { - return mDelegate.getColumnNumber(); - } - - // -- We don't care much about the methods that follow. - - @Override - public void require(int i, String s, String s1) throws XmlPullParserException, IOException { - throw new UnsupportedOperationException("Only few parser methods are supported."); - } - - @Override - public boolean getFeature(String s) { - throw new UnsupportedOperationException("Only few parser methods are supported."); - } - - @Override - public void defineEntityReplacementText(String s, String s1) throws XmlPullParserException { - throw new UnsupportedOperationException("Only few parser methods are supported."); - } - - @Override - public Object getProperty(String s) { - throw new UnsupportedOperationException("Only few parser methods are supported."); - } - - @Override - public int nextToken() throws XmlPullParserException, IOException { - throw new UnsupportedOperationException("Only few parser methods are supported."); - } - - @Override - public int getNamespaceCount(int i) throws XmlPullParserException { - throw new UnsupportedOperationException("Only few parser methods are supported."); - } - - @Override - public String getNamespacePrefix(int i) throws XmlPullParserException { - throw new UnsupportedOperationException("Only few parser methods are supported."); - } - - @Override - public String getNamespaceUri(int i) throws XmlPullParserException { - throw new UnsupportedOperationException("Only few parser methods are supported."); - } - - @Override - public boolean isWhitespace() throws XmlPullParserException { - throw new UnsupportedOperationException("Only few parser methods are supported."); - } - - @Override - public char[] getTextCharacters(int[] ints) { - throw new UnsupportedOperationException("Only few parser methods are supported."); - } - - @Override - public String getPrefix() { - throw new UnsupportedOperationException("Only few parser methods are supported."); - } - - @Override - public boolean isEmptyElementTag() throws XmlPullParserException { - throw new UnsupportedOperationException("Only few parser methods are supported."); - } - - @Override - public int getAttributeCount() { - throw new UnsupportedOperationException("Only few parser methods are supported."); - } - - @Override - public String getAttributeNamespace(int i) { - throw new UnsupportedOperationException("Only few parser methods are supported."); - } - - @Override - public String getAttributeName(int i) { - throw new UnsupportedOperationException("Only few parser methods are supported."); - } - - @Override - public String getAttributePrefix(int i) { - throw new UnsupportedOperationException("Only few parser methods are supported."); - } - - @Override - public String getAttributeType(int i) { - throw new UnsupportedOperationException("Only few parser methods are supported."); - } - - @Override - public boolean isAttributeDefault(int i) { - throw new UnsupportedOperationException("Only few parser methods are supported."); - } - - @Override - public String getAttributeValue(int i) { - throw new UnsupportedOperationException("Only few parser methods are supported."); - } - - @Override - public String nextText() throws XmlPullParserException, IOException { - throw new UnsupportedOperationException("Only few parser methods are supported."); - } - - @Override - public int nextTag() throws XmlPullParserException, IOException { - throw new UnsupportedOperationException("Only few parser methods are supported."); - } -} 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 deleted file mode 100644 index 1ae9cb646cf3..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.impl; - - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import android.annotation.NonNull; -import android.annotation.Nullable; - -import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; - -/** - * A factory for {@link XmlPullParser}. - * - */ -public class ParserFactory { - - public final static boolean LOG_PARSER = false; - - // Used to get a new XmlPullParser from the client. - @Nullable - private static com.android.ide.common.rendering.api.ParserFactory sParserFactory; - - public static void setParserFactory( - @Nullable com.android.ide.common.rendering.api.ParserFactory parserFactory) { - sParserFactory = parserFactory; - } - - @NonNull - public static XmlPullParser create(@NonNull File f) - throws XmlPullParserException, FileNotFoundException { - return create(f, false); - } - - public static XmlPullParser create(@NonNull File f, boolean isLayout) - throws XmlPullParserException, FileNotFoundException { - InputStream stream = new FileInputStream(f); - return create(stream, f.getName(), f.length(), isLayout); - } - @NonNull - public static XmlPullParser create(@NonNull InputStream stream, @Nullable String name) - throws XmlPullParserException { - return create(stream, name, -1, false); - } - - @NonNull - private static XmlPullParser create(@NonNull InputStream stream, @Nullable String name, - long size, boolean isLayout) throws XmlPullParserException { - XmlPullParser parser = instantiateParser(name); - - stream = readAndClose(stream, name, size); - - parser.setInput(stream, null); - if (isLayout) { - try { - return new LayoutParserWrapper(parser).peekTillLayoutStart(); - } catch (IOException e) { - throw new XmlPullParserException(null, parser, e); - } - } - return parser; - } - - @NonNull - public static XmlPullParser instantiateParser(@Nullable String name) - throws XmlPullParserException { - if (sParserFactory == null) { - throw new XmlPullParserException("ParserFactory not initialized."); - } - XmlPullParser parser = sParserFactory.createParser(name); - parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); - return parser; - } - - @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"); - } - int intSize = (int) size; - - // create a buffered reader to facilitate reading. - BufferedInputStream bufferedStream = new BufferedInputStream(stream); - try { - int avail; - if (intSize != -1) { - avail = intSize; - } else { - // get the size to read. - avail = bufferedStream.available(); - } - - // create the initial buffer and read it. - byte[] buffer = new byte[avail]; - int read = stream.read(buffer); - - // this is the easy case. - if (read == intSize) { - return new ByteArrayInputStream(buffer); - } - - // check if there is more to read (read() does not necessarily read all that - // available() returned!) - while ((avail = bufferedStream.available()) > 0) { - if (read + avail > buffer.length) { - // just allocate what is needed. We're mostly reading small files - // so it shouldn't be too problematic. - byte[] moreBuffer = new byte[read + avail]; - System.arraycopy(buffer, 0, moreBuffer, 0, read); - buffer = moreBuffer; - } - - read += stream.read(buffer, read, avail); - } - - // return a new stream encapsulating this buffer. - return new ByteArrayInputStream(buffer); - - } catch (IOException e) { - throw new XmlPullParserException("Failed to read " + name, null, e); - } finally { - try { - bufferedStream.close(); - } catch (IOException ignored) { - } - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PlayAnimationThread.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PlayAnimationThread.java deleted file mode 100644 index 7b701802b9a5..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PlayAnimationThread.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.impl; - -import com.android.ide.common.rendering.api.IAnimationListener; -import com.android.ide.common.rendering.api.Result; -import com.android.ide.common.rendering.api.Result.Status; - -import android.animation.AnimationThread; -import android.animation.Animator; - -public class PlayAnimationThread extends AnimationThread { - - private final Animator mAnimator; - - public PlayAnimationThread(Animator animator, RenderSessionImpl scene, String animName, - IAnimationListener listener) { - super(scene, animName, listener); - mAnimator = animator; - } - - @Override - public Result preAnimation() { - // start the animation. This will send a message to the handler right away, so - // the queue is filled when this method returns. - mAnimator.start(); - - return Status.SUCCESS.createResult(); - } - - @Override - public void postAnimation() { - // nothing to be done. - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java deleted file mode 100644 index 70e2eb17794a..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java +++ /dev/null @@ -1,107 +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 com.android.layoutlib.bridge.impl; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.layoutlib.bridge.Bridge; - -import android.graphics.BlendComposite; -import android.graphics.BlendComposite.BlendingMode; -import android.graphics.PorterDuff; -import android.graphics.PorterDuff.Mode; -import android.graphics.PorterDuffColorFilter_Delegate; - -import java.awt.AlphaComposite; -import java.awt.Composite; - -/** - * Provides various utility methods for {@link PorterDuffColorFilter_Delegate}. - */ -public final class PorterDuffUtility { - - private static final int MODES_COUNT = Mode.values().length; - - // Make the class non-instantiable. - private PorterDuffUtility() { - } - - /** - * Convert the porterDuffMode from the framework to its corresponding enum. This defaults to - * {@link Mode#SRC_OVER} for invalid modes. - */ - public static Mode getPorterDuffMode(int porterDuffMode) { - if (porterDuffMode >= 0 && porterDuffMode < MODES_COUNT) { - return PorterDuff.intToMode(porterDuffMode); - } - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - String.format("Unknown PorterDuff.Mode: %1$d", porterDuffMode), null); - assert false; - return Mode.SRC_OVER; - } - - /** - * A utility method to get the {@link Composite} that represents the filter for the given - * PorterDuff mode and the alpha. Defaults to {@link Mode#SRC_OVER} for invalid modes. - */ - public static Composite getComposite(Mode mode, int alpha255) { - float alpha1 = alpha255 != 0xFF ? alpha255 / 255.f : 1.f; - switch (mode) { - case CLEAR: - return AlphaComposite.getInstance(AlphaComposite.CLEAR, alpha1); - case SRC: - return AlphaComposite.getInstance(AlphaComposite.SRC, alpha1); - case DST: - return AlphaComposite.getInstance(AlphaComposite.DST, alpha1); - case SRC_OVER: - return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha1); - case DST_OVER: - return AlphaComposite.getInstance(AlphaComposite.DST_OVER, alpha1); - case SRC_IN: - return AlphaComposite.getInstance(AlphaComposite.SRC_IN, alpha1); - case DST_IN: - return AlphaComposite.getInstance(AlphaComposite.DST_IN, alpha1); - case SRC_OUT: - return AlphaComposite.getInstance(AlphaComposite.SRC_OUT, alpha1); - case DST_OUT: - return AlphaComposite.getInstance(AlphaComposite.DST_OUT, alpha1); - case SRC_ATOP: - return AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha1); - case DST_ATOP: - return AlphaComposite.getInstance(AlphaComposite.DST_ATOP, alpha1); - case XOR: - return AlphaComposite.getInstance(AlphaComposite.XOR, alpha1); - case DARKEN: - return BlendComposite.getInstance(BlendingMode.DARKEN, alpha1); - case LIGHTEN: - return BlendComposite.getInstance(BlendingMode.LIGHTEN, alpha1); - case MULTIPLY: - return BlendComposite.getInstance(BlendingMode.MULTIPLY, alpha1); - case SCREEN: - return BlendComposite.getInstance(BlendingMode.SCREEN, alpha1); - case ADD: - return BlendComposite.getInstance(BlendingMode.ADD, alpha1); - case OVERLAY: - return BlendComposite.getInstance(BlendingMode.OVERLAY, alpha1); - default: - Bridge.getLog().fidelityWarning(LayoutLog.TAG_BROKEN, - String.format("Unsupported PorterDuff Mode: %1$s", mode.name()), - null, null /*data*/); - - return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha1); - } - } -} 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 deleted file mode 100644 index 0c537533479e..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.impl; - -import com.android.ide.common.rendering.api.HardwareConfig; -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.ide.common.rendering.api.RenderParams; -import com.android.ide.common.rendering.api.RenderResources; -import com.android.ide.common.rendering.api.RenderResources.FrameworkResourceIdProvider; -import com.android.ide.common.rendering.api.Result; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.resources.Density; -import com.android.resources.ResourceType; -import com.android.resources.ScreenOrientation; -import com.android.resources.ScreenRound; -import com.android.resources.ScreenSize; - -import android.content.res.Configuration; -import android.os.HandlerThread_Delegate; -import android.util.DisplayMetrics; -import android.view.ViewConfiguration_Accessor; -import android.view.inputmethod.InputMethodManager; -import android.view.inputmethod.InputMethodManager_Accessor; - -import java.util.Locale; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.ReentrantLock; - -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; - -/** - * Base class for rendering action. - * - * It provides life-cycle methods to init and stop the rendering. - * The most important methods are: - * {@link #init(long)} and {@link #acquire(long)} to start a rendering and {@link #release()} - * after the rendering. - * - * - * @param <T> the {@link RenderParams} implementation - * - */ -public abstract class RenderAction<T extends RenderParams> extends FrameworkResourceIdProvider { - - /** - * The current context being rendered. This is set through {@link #acquire(long)} and - * {@link #init(long)}, and unset in {@link #release()}. - */ - private static BridgeContext sCurrentContext = null; - - private final T mParams; - - private BridgeContext mContext; - - /** - * Creates a renderAction. - * <p> - * This <b>must</b> be followed by a call to {@link RenderAction#init(long)}, which act as a - * call to {@link RenderAction#acquire(long)} - * - * @param params the RenderParams. This must be a copy that the action can keep - * - */ - protected RenderAction(T params) { - mParams = params; - } - - /** - * Initializes and acquires the scene, creating various Android objects such as context, - * inflater, and parser. - * - * @param timeout the time to wait if another rendering is happening. - * - * @return whether the scene was prepared - * - * @see #acquire(long) - * @see #release() - */ - public Result init(long timeout) { - // acquire the lock. if the result is null, lock was just acquired, otherwise, return - // the result. - Result result = acquireLock(timeout); - if (result != null) { - return result; - } - - HardwareConfig hardwareConfig = mParams.getHardwareConfig(); - - // setup the display Metrics. - DisplayMetrics metrics = new DisplayMetrics(); - metrics.densityDpi = metrics.noncompatDensityDpi = - hardwareConfig.getDensity().getDpiValue(); - - metrics.density = metrics.noncompatDensity = - metrics.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT; - - metrics.scaledDensity = metrics.noncompatScaledDensity = metrics.density; - - metrics.widthPixels = metrics.noncompatWidthPixels = hardwareConfig.getScreenWidth(); - metrics.heightPixels = metrics.noncompatHeightPixels = hardwareConfig.getScreenHeight(); - metrics.xdpi = metrics.noncompatXdpi = hardwareConfig.getXdpi(); - metrics.ydpi = metrics.noncompatYdpi = hardwareConfig.getYdpi(); - - RenderResources resources = mParams.getResources(); - - // build the context - mContext = new BridgeContext(mParams.getProjectKey(), metrics, resources, - mParams.getAssets(), mParams.getLayoutlibCallback(), getConfiguration(mParams), - mParams.getTargetSdkVersion(), mParams.isRtlSupported()); - - setUp(); - - return SUCCESS.createResult(); - } - - /** - * Prepares the scene for action. - * <p> - * This call is blocking if another rendering/inflating is currently happening, and will return - * whether the preparation worked. - * - * The preparation can fail if another rendering took too long and the timeout was elapsed. - * - * More than one call to this from the same thread will have no effect and will return - * {@link Result.Status#SUCCESS}. - * - * After scene actions have taken place, only one call to {@link #release()} must be - * done. - * - * @param timeout the time to wait if another rendering is happening. - * - * @return whether the scene was prepared - * - * @see #release() - * - * @throws IllegalStateException if {@link #init(long)} was never called. - */ - public Result acquire(long timeout) { - if (mContext == null) { - throw new IllegalStateException("After scene creation, #init() must be called"); - } - - // acquire the lock. if the result is null, lock was just acquired, otherwise, return - // the result. - Result result = acquireLock(timeout); - if (result != null) { - return result; - } - - setUp(); - - return SUCCESS.createResult(); - } - - /** - * Acquire the lock so that the scene can be acted upon. - * <p> - * This returns null if the lock was just acquired, otherwise it returns - * {@link Result.Status#SUCCESS} if the lock already belonged to that thread, or another - * instance (see {@link Result#getStatus()}) if an error occurred. - * - * @param timeout the time to wait if another rendering is happening. - * @return null if the lock was just acquire or another result depending on the state. - * - * @throws IllegalStateException if the current context is different than the one owned by - * the scene. - */ - private Result acquireLock(long timeout) { - ReentrantLock lock = Bridge.getLock(); - if (!lock.isHeldByCurrentThread()) { - try { - boolean acquired = lock.tryLock(timeout, TimeUnit.MILLISECONDS); - - if (!acquired) { - return ERROR_TIMEOUT.createResult(); - } - } catch (InterruptedException e) { - return ERROR_LOCK_INTERRUPTED.createResult(); - } - } else { - // This thread holds the lock already. Checks that this wasn't for a different context. - // If this is called by init, mContext will be null and so should sCurrentContext - // anyway - if (mContext != sCurrentContext) { - throw new IllegalStateException("Acquiring different scenes from same thread without releases"); - } - return SUCCESS.createResult(); - } - - return null; - } - - /** - * Cleans up the scene after an action. - */ - public void release() { - ReentrantLock lock = Bridge.getLock(); - - // with the use of finally blocks, it is possible to find ourself calling this - // without a successful call to prepareScene. This test makes sure that unlock() will - // not throw IllegalMonitorStateException. - if (lock.isHeldByCurrentThread()) { - tearDown(); - lock.unlock(); - } - } - - /** - * Sets up the session for rendering. - * <p/> - * The counterpart is {@link #tearDown()}. - */ - private void setUp() { - // setup the ParserFactory - ParserFactory.setParserFactory(mParams.getLayoutlibCallback().getParserFactory()); - - // make sure the Resources object references the context (and other objects) for this - // scene - mContext.initResources(); - sCurrentContext = mContext; - - // create an InputMethodManager - InputMethodManager.getInstance(); - - LayoutLog currentLog = mParams.getLog(); - Bridge.setLog(currentLog); - mContext.getRenderResources().setFrameworkResourceIdProvider(this); - mContext.getRenderResources().setLogger(currentLog); - } - - /** - * Tear down the session after rendering. - * <p/> - * The counterpart is {@link #setUp()}. - */ - private void tearDown() { - // The context may be null, if there was an error during init(). - if (mContext != null) { - // Make sure to remove static references, otherwise we could not unload the lib - mContext.disposeResources(); - } - - if (sCurrentContext != null) { - // quit HandlerThread created during this session. - HandlerThread_Delegate.cleanUp(sCurrentContext); - } - - // clear the stored ViewConfiguration since the map is per density and not per context. - ViewConfiguration_Accessor.clearConfigurations(); - - // remove the InputMethodManager - InputMethodManager_Accessor.resetInstance(); - - sCurrentContext = null; - - Bridge.setLog(null); - if (mContext != null) { - mContext.getRenderResources().setFrameworkResourceIdProvider(null); - mContext.getRenderResources().setLogger(null); - } - ParserFactory.setParserFactory(null); - } - - public static BridgeContext getCurrentContext() { - return sCurrentContext; - } - - protected T getParams() { - return mParams; - } - - protected BridgeContext getContext() { - return mContext; - } - - /** - * Returns the log associated with the session. - * @return the log or null if there are none. - */ - public LayoutLog getLog() { - if (mParams != null) { - return mParams.getLog(); - } - - return null; - } - - /** - * Checks that the lock is owned by the current thread and that the current context is the one - * from this scene. - * - * @throws IllegalStateException if the current context is different than the one owned by - * the scene, or if {@link #acquire(long)} was not called. - */ - protected void checkLock() { - ReentrantLock lock = Bridge.getLock(); - if (!lock.isHeldByCurrentThread()) { - throw new IllegalStateException("scene must be acquired first. see #acquire(long)"); - } - if (sCurrentContext != mContext) { - throw new IllegalStateException("Thread acquired a scene but is rendering a different one"); - } - } - - // VisibleForTesting - public static Configuration getConfiguration(RenderParams params) { - Configuration config = new Configuration(); - - HardwareConfig hardwareConfig = params.getHardwareConfig(); - - ScreenSize screenSize = hardwareConfig.getScreenSize(); - if (screenSize != null) { - switch (screenSize) { - case SMALL: - config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_SMALL; - break; - case NORMAL: - config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_NORMAL; - break; - case LARGE: - config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_LARGE; - break; - case XLARGE: - config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_XLARGE; - break; - } - } - - Density density = hardwareConfig.getDensity(); - if (density == null) { - density = Density.MEDIUM; - } - - config.screenWidthDp = hardwareConfig.getScreenWidth() / density.getDpiValue(); - config.screenHeightDp = hardwareConfig.getScreenHeight() / density.getDpiValue(); - if (config.screenHeightDp < config.screenWidthDp) { - //noinspection SuspiciousNameCombination - config.smallestScreenWidthDp = config.screenHeightDp; - } else { - config.smallestScreenWidthDp = config.screenWidthDp; - } - config.densityDpi = density.getDpiValue(); - - // never run in compat mode: - config.compatScreenWidthDp = config.screenWidthDp; - config.compatScreenHeightDp = config.screenHeightDp; - - ScreenOrientation orientation = hardwareConfig.getOrientation(); - if (orientation != null) { - switch (orientation) { - case PORTRAIT: - config.orientation = Configuration.ORIENTATION_PORTRAIT; - break; - case LANDSCAPE: - config.orientation = Configuration.ORIENTATION_LANDSCAPE; - break; - case SQUARE: - //noinspection deprecation - config.orientation = Configuration.ORIENTATION_SQUARE; - break; - } - } else { - config.orientation = Configuration.ORIENTATION_UNDEFINED; - } - - ScreenRound roundness = hardwareConfig.getScreenRoundness(); - if (roundness != null) { - switch (roundness) { - case ROUND: - config.screenLayout |= Configuration.SCREENLAYOUT_ROUND_YES; - break; - case NOTROUND: - config.screenLayout |= Configuration.SCREENLAYOUT_ROUND_NO; - } - } else { - config.screenLayout |= Configuration.SCREENLAYOUT_ROUND_UNDEFINED; - } - String locale = params.getLocale(); - if (locale != null && !locale.isEmpty()) config.locale = new Locale(locale); - - // TODO: fill in more config info. - - return config; - } - - - // --- FrameworkResourceIdProvider methods - - @Override - public Integer getId(ResourceType resType, String resName) { - return Bridge.getResourceId(resType, resName); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java deleted file mode 100644 index d797eecad3dd..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.impl; - -import com.android.ide.common.rendering.api.DrawableParams; -import com.android.ide.common.rendering.api.HardwareConfig; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.rendering.api.Result; -import com.android.ide.common.rendering.api.Result.Status; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.android.RenderParamsFlags; -import com.android.resources.ResourceType; - -import android.graphics.Bitmap; -import android.graphics.Bitmap_Delegate; -import android.graphics.Canvas; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.StateListDrawable; -import android.view.AttachInfo_Accessor; -import android.view.View.MeasureSpec; -import android.widget.FrameLayout; - -import java.awt.AlphaComposite; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * Action to render a given Drawable provided through {@link DrawableParams#getDrawable()}. - * - * The class only provides a simple {@link #render()} method, but the full life-cycle of the - * action must be respected. - * - * @see RenderAction - * - */ -public class RenderDrawable extends RenderAction<DrawableParams> { - - public RenderDrawable(DrawableParams params) { - super(new DrawableParams(params)); - } - - public Result render() { - checkLock(); - // get the drawable resource value - DrawableParams params = getParams(); - HardwareConfig hardwareConfig = params.getHardwareConfig(); - ResourceValue drawableResource = params.getDrawable(); - - // resolve it - BridgeContext context = getContext(); - drawableResource = context.getRenderResources().resolveResValue(drawableResource); - - if (drawableResource == null) { - return Status.ERROR_NOT_A_DRAWABLE.createResult(); - } - - ResourceType resourceType = drawableResource.getResourceType(); - if (resourceType != ResourceType.DRAWABLE && resourceType != ResourceType.MIPMAP) { - return Status.ERROR_NOT_A_DRAWABLE.createResult(); - } - - Drawable d = ResourceHelper.getDrawable(drawableResource, context); - - final Boolean allStates = - params.getFlag(RenderParamsFlags.FLAG_KEY_RENDER_ALL_DRAWABLE_STATES); - if (allStates == Boolean.TRUE) { - final List<BufferedImage> result; - - if (d instanceof StateListDrawable) { - result = new ArrayList<BufferedImage>(); - final StateListDrawable stateList = (StateListDrawable) d; - for (int i = 0; i < stateList.getStateCount(); i++) { - final Drawable stateDrawable = stateList.getStateDrawable(i); - result.add(renderImage(hardwareConfig, stateDrawable, context)); - } - } else { - result = Collections.singletonList(renderImage(hardwareConfig, d, context)); - } - - return Status.SUCCESS.createResult(result); - } else { - BufferedImage image = renderImage(hardwareConfig, d, context); - return Status.SUCCESS.createResult(image); - } - } - - private BufferedImage renderImage(HardwareConfig hardwareConfig, Drawable d, - BridgeContext context) { - // create a simple FrameLayout - FrameLayout content = new FrameLayout(context); - - // get the actual Drawable object to draw - content.setBackground(d); - - // set the AttachInfo on the root view. - AttachInfo_Accessor.setAttachInfo(content); - - - // measure - int w = d.getIntrinsicWidth(); - int h = d.getIntrinsicHeight(); - - final int screenWidth = hardwareConfig.getScreenWidth(); - final int screenHeight = hardwareConfig.getScreenHeight(); - - if (w == -1 || h == -1) { - // Use screen size when either intrinsic width or height isn't available - w = screenWidth; - h = screenHeight; - } else if (w > screenWidth || h > screenHeight) { - // If image wouldn't fit to the screen, resize it to avoid cropping. - - // We need to find scale such that scale * w <= screenWidth, scale * h <= screenHeight - double scale = Math.min((double) screenWidth / w, (double) screenHeight / h); - - // scale * w / scale * h = w / h, so, proportions are preserved. - w = (int) Math.floor(scale * w); - h = (int) Math.floor(scale * h); - } - - int w_spec = MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY); - int h_spec = MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY); - content.measure(w_spec, h_spec); - - // now do the layout. - content.layout(0, 0, w, h); - - // preDraw setup - AttachInfo_Accessor.dispatchOnPreDraw(content); - - // draw into a new image - BufferedImage image = getImage(w, h); - - // create an Android bitmap around the BufferedImage - Bitmap bitmap = Bitmap_Delegate.createBitmap(image, - true /*isMutable*/, hardwareConfig.getDensity()); - - // create a Canvas around the Android bitmap - Canvas canvas = new Canvas(bitmap); - canvas.setDensity(hardwareConfig.getDensity().getDpiValue()); - - // and draw - content.draw(canvas); - return image; - } - - protected BufferedImage getImage(int w, int h) { - BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); - Graphics2D gc = image.createGraphics(); - gc.setComposite(AlphaComposite.Src); - - gc.setColor(new Color(0x00000000, true)); - gc.fillRect(0, 0, w, h); - - // done - gc.dispose(); - - return image; - } - -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java deleted file mode 100644 index d21955e35409..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java +++ /dev/null @@ -1,1557 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.impl; - -import com.android.ide.common.rendering.api.AdapterBinding; -import com.android.ide.common.rendering.api.HardwareConfig; -import com.android.ide.common.rendering.api.IAnimationListener; -import com.android.ide.common.rendering.api.ILayoutPullParser; -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.ide.common.rendering.api.LayoutlibCallback; -import com.android.ide.common.rendering.api.RenderResources; -import com.android.ide.common.rendering.api.RenderSession; -import com.android.ide.common.rendering.api.ResourceReference; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.rendering.api.Result; -import com.android.ide.common.rendering.api.Result.Status; -import com.android.ide.common.rendering.api.SessionParams; -import com.android.ide.common.rendering.api.SessionParams.RenderingMode; -import com.android.ide.common.rendering.api.ViewInfo; -import com.android.ide.common.rendering.api.ViewType; -import com.android.internal.view.menu.ActionMenuItemView; -import com.android.internal.view.menu.BridgeMenuItemImpl; -import com.android.internal.view.menu.IconMenuItemView; -import com.android.internal.view.menu.ListMenuItemView; -import com.android.internal.view.menu.MenuItemImpl; -import com.android.internal.view.menu.MenuView; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes; -import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; -import com.android.layoutlib.bridge.android.RenderParamsFlags; -import com.android.layoutlib.bridge.android.graphics.NopCanvas; -import com.android.layoutlib.bridge.android.support.DesignLibUtil; -import com.android.layoutlib.bridge.android.support.SupportPreferencesUtil; -import com.android.layoutlib.bridge.impl.binding.FakeAdapter; -import com.android.layoutlib.bridge.impl.binding.FakeExpandableAdapter; -import com.android.resources.ResourceType; -import com.android.tools.layoutlib.java.System_Delegate; -import com.android.util.Pair; -import com.android.util.PropertiesMap; - -import android.animation.AnimationThread; -import android.animation.Animator; -import android.animation.AnimatorInflater; -import android.animation.LayoutTransition; -import android.animation.LayoutTransition.TransitionListener; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.app.Fragment_Delegate; -import android.graphics.Bitmap; -import android.graphics.Bitmap_Delegate; -import android.graphics.Canvas; -import android.os.Looper; -import android.preference.Preference_Delegate; -import android.view.AttachInfo_Accessor; -import android.view.BridgeInflater; -import android.view.Choreographer_Delegate; -import android.view.IWindowManager; -import android.view.IWindowManagerImpl; -import android.view.Surface; -import android.view.View; -import android.view.View.MeasureSpec; -import android.view.ViewGroup; -import android.view.ViewGroup.LayoutParams; -import android.view.ViewGroup.MarginLayoutParams; -import android.view.ViewParent; -import android.view.WindowManagerGlobal_Delegate; -import android.widget.AbsListView; -import android.widget.AbsSpinner; -import android.widget.ActionMenuView; -import android.widget.AdapterView; -import android.widget.ExpandableListView; -import android.widget.FrameLayout; -import android.widget.LinearLayout; -import android.widget.ListView; -import android.widget.QuickContactBadge; -import android.widget.TabHost; -import android.widget.TabHost.TabSpec; -import android.widget.TabWidget; - -import java.awt.AlphaComposite; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import static com.android.ide.common.rendering.api.Result.Status.ERROR_ANIM_NOT_FOUND; -import static com.android.ide.common.rendering.api.Result.Status.ERROR_INFLATION; -import static com.android.ide.common.rendering.api.Result.Status.ERROR_NOT_INFLATED; -import static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN; -import static com.android.ide.common.rendering.api.Result.Status.ERROR_VIEWGROUP_NO_CHILDREN; -import static com.android.ide.common.rendering.api.Result.Status.SUCCESS; -import static com.android.layoutlib.bridge.util.ReflectionUtils.isInstanceOf; - -/** - * Class implementing the render session. - * <p/> - * A session is a stateful representation of a layout file. It is initialized with data coming - * through the {@link Bridge} API to inflate the layout. Further actions and rendering can then - * be done on the layout. - */ -public class RenderSessionImpl extends RenderAction<SessionParams> { - - private static final Canvas NOP_CANVAS = new NopCanvas(); - - // scene state - private RenderSession mScene; - private BridgeXmlBlockParser mBlockParser; - private BridgeInflater mInflater; - private ViewGroup mViewRoot; - private FrameLayout mContentRoot; - private Canvas mCanvas; - private int mMeasuredScreenWidth = -1; - private int mMeasuredScreenHeight = -1; - private boolean mIsAlphaChannelImage; - /** If >= 0, a frame will be executed */ - private long mElapsedFrameTimeNanos = -1; - /** True if one frame has been already executed to start the animations */ - private boolean mFirstFrameExecuted = false; - - // information being returned through the API - private BufferedImage mImage; - private List<ViewInfo> mViewInfoList; - private List<ViewInfo> mSystemViewInfoList; - private Layout.Builder mLayoutBuilder; - private boolean mNewRenderSize; - - private static final class PostInflateException extends Exception { - private static final long serialVersionUID = 1L; - - private PostInflateException(String message) { - super(message); - } - } - - /** - * Creates a layout scene with all the information coming from the layout bridge API. - * <p> - * This <b>must</b> be followed by a call to {@link RenderSessionImpl#init(long)}, - * which act as a - * call to {@link RenderSessionImpl#acquire(long)} - * - * @see Bridge#createSession(SessionParams) - */ - public RenderSessionImpl(SessionParams params) { - super(new SessionParams(params)); - } - - /** - * Initializes and acquires the scene, creating various Android objects such as context, - * inflater, and parser. - * - * @param timeout the time to wait if another rendering is happening. - * - * @return whether the scene was prepared - * - * @see #acquire(long) - * @see #release() - */ - @Override - public Result init(long timeout) { - Result result = super.init(timeout); - if (!result.isSuccess()) { - return result; - } - - SessionParams params = getParams(); - BridgeContext context = getContext(); - - // use default of true in case it's not found to use alpha by default - mIsAlphaChannelImage = ResourceHelper.getBooleanThemeValue(params.getResources(), - "windowIsFloating", true, true); - - mLayoutBuilder = new Layout.Builder(params, context); - - // FIXME: find those out, and possibly add them to the render params - boolean hasNavigationBar = true; - //noinspection ConstantConditions - IWindowManager iwm = new IWindowManagerImpl(getContext().getConfiguration(), - context.getMetrics(), Surface.ROTATION_0, hasNavigationBar); - WindowManagerGlobal_Delegate.setWindowManagerService(iwm); - - // build the inflater and parser. - mInflater = new BridgeInflater(context, params.getLayoutlibCallback()); - context.setBridgeInflater(mInflater); - - mBlockParser = new BridgeXmlBlockParser(params.getLayoutDescription(), context, false); - - return SUCCESS.createResult(); - } - - /** - * Measures the the current layout if needed (see {@link #invalidateRenderingSize}). - */ - private void measureLayout(@NonNull SessionParams params) { - // only do the screen measure when needed. - if (mMeasuredScreenWidth != -1) { - return; - } - - RenderingMode renderingMode = params.getRenderingMode(); - HardwareConfig hardwareConfig = params.getHardwareConfig(); - - mNewRenderSize = true; - mMeasuredScreenWidth = hardwareConfig.getScreenWidth(); - mMeasuredScreenHeight = hardwareConfig.getScreenHeight(); - - if (renderingMode != RenderingMode.NORMAL) { - int widthMeasureSpecMode = renderingMode.isHorizExpand() ? - MeasureSpec.UNSPECIFIED // this lets us know the actual needed size - : MeasureSpec.EXACTLY; - int heightMeasureSpecMode = renderingMode.isVertExpand() ? - MeasureSpec.UNSPECIFIED // this lets us know the actual needed size - : MeasureSpec.EXACTLY; - - // We used to compare the measured size of the content to the screen size but - // this does not work anymore due to the 2 following issues: - // - If the content is in a decor (system bar, title/action bar), the root view - // will not resize even with the UNSPECIFIED because of the embedded layout. - // - If there is no decor, but a dialog frame, then the dialog padding prevents - // comparing the size of the content to the screen frame (as it would not - // take into account the dialog padding). - - // The solution is to first get the content size in a normal rendering, inside - // the decor or the dialog padding. - // Then measure only the content with UNSPECIFIED to see the size difference - // and apply this to the screen size. - - View measuredView = mContentRoot.getChildAt(0); - - // first measure the full layout, with EXACTLY to get the size of the - // content as it is inside the decor/dialog - @SuppressWarnings("deprecation") - Pair<Integer, Integer> exactMeasure = measureView( - mViewRoot, measuredView, - mMeasuredScreenWidth, MeasureSpec.EXACTLY, - mMeasuredScreenHeight, MeasureSpec.EXACTLY); - - // now measure the content only using UNSPECIFIED (where applicable, based on - // the rendering mode). This will give us the size the content needs. - @SuppressWarnings("deprecation") - Pair<Integer, Integer> result = measureView( - mContentRoot, mContentRoot.getChildAt(0), - mMeasuredScreenWidth, widthMeasureSpecMode, - mMeasuredScreenHeight, heightMeasureSpecMode); - - // If measuredView is not null, exactMeasure nor result will be null. - assert exactMeasure != null; - assert result != null; - - // now look at the difference and add what is needed. - if (renderingMode.isHorizExpand()) { - int measuredWidth = exactMeasure.getFirst(); - int neededWidth = result.getFirst(); - if (neededWidth > measuredWidth) { - mMeasuredScreenWidth += neededWidth - measuredWidth; - } - if (mMeasuredScreenWidth < measuredWidth) { - // If the screen width is less than the exact measured width, - // expand to match. - mMeasuredScreenWidth = measuredWidth; - } - } - - if (renderingMode.isVertExpand()) { - int measuredHeight = exactMeasure.getSecond(); - int neededHeight = result.getSecond(); - if (neededHeight > measuredHeight) { - mMeasuredScreenHeight += neededHeight - measuredHeight; - } - if (mMeasuredScreenHeight < measuredHeight) { - // If the screen height is less than the exact measured height, - // expand to match. - mMeasuredScreenHeight = measuredHeight; - } - } - } - } - - /** - * Inflates the layout. - * <p> - * {@link #acquire(long)} must have been called before this. - * - * @throws IllegalStateException if the current context is different than the one owned by - * the scene, or if {@link #init(long)} was not called. - */ - public Result inflate() { - checkLock(); - - try { - mViewRoot = new Layout(mLayoutBuilder); - mLayoutBuilder = null; // Done with the builder. - mContentRoot = ((Layout) mViewRoot).getContentRoot(); - SessionParams params = getParams(); - BridgeContext context = getContext(); - - if (Bridge.isLocaleRtl(params.getLocale())) { - if (!params.isRtlSupported()) { - Bridge.getLog().warning(LayoutLog.TAG_RTL_NOT_ENABLED, - "You are using a right-to-left " + - "(RTL) locale but RTL is not enabled", null); - } else if (params.getSimulatedPlatformVersion() < 17) { - // This will render ok because we are using the latest layoutlib but at least - // warn the user that this might fail in a real device. - Bridge.getLog().warning(LayoutLog.TAG_RTL_NOT_SUPPORTED, "You are using a " + - "right-to-left " + - "(RTL) locale but RTL is not supported for API level < 17", null); - } - } - - // Sets the project callback (custom view loader) to the fragment delegate so that - // it can instantiate the custom Fragment. - Fragment_Delegate.setLayoutlibCallback(params.getLayoutlibCallback()); - - String rootTag = params.getFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG); - boolean isPreference = "PreferenceScreen".equals(rootTag); - View view; - if (isPreference) { - // First try to use the support library inflater. If something fails, fallback - // to the system preference inflater. - view = SupportPreferencesUtil.inflatePreference(getContext(), mBlockParser, - mContentRoot); - if (view == null) { - view = Preference_Delegate.inflatePreference(getContext(), mBlockParser, - mContentRoot); - } - } else { - view = mInflater.inflate(mBlockParser, mContentRoot); - } - - // done with the parser, pop it. - context.popParser(); - - Fragment_Delegate.setLayoutlibCallback(null); - - // set the AttachInfo on the root view. - AttachInfo_Accessor.setAttachInfo(mViewRoot); - - // post-inflate process. For now this supports TabHost/TabWidget - postInflateProcess(view, params.getLayoutlibCallback(), isPreference ? view : null); - mInflater.onDoneInflation(); - - setActiveToolbar(view, context, params); - - measureLayout(params); - measureView(mViewRoot, null /*measuredView*/, - mMeasuredScreenWidth, MeasureSpec.EXACTLY, - mMeasuredScreenHeight, MeasureSpec.EXACTLY); - mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight); - mSystemViewInfoList = - visitAllChildren(mViewRoot, 0, 0, params.getExtendedViewInfoMode(), - false); - - return SUCCESS.createResult(); - } catch (PostInflateException e) { - return ERROR_INFLATION.createResult(e.getMessage(), e); - } catch (Throwable e) { - // get the real cause of the exception. - Throwable t = e; - while (t.getCause() != null) { - t = t.getCause(); - } - - return ERROR_INFLATION.createResult(t.getMessage(), t); - } - } - - /** - * Sets the time for which the next frame will be selected. The time is the elapsed time from - * the current system nanos time. You - */ - public void setElapsedFrameTimeNanos(long nanos) { - mElapsedFrameTimeNanos = nanos; - } - - /** - * Runs a layout pass for the given view root - */ - private static void doLayout(@NonNull BridgeContext context, @NonNull ViewGroup viewRoot, - int width, int height) { - // measure again with the size we need - // This must always be done before the call to layout - measureView(viewRoot, null /*measuredView*/, - width, MeasureSpec.EXACTLY, - height, MeasureSpec.EXACTLY); - - // now do the layout. - viewRoot.layout(0, 0, width, height); - handleScrolling(context, viewRoot); - } - - /** - * Renders the given view hierarchy to the passed canvas and returns the result of the render - * operation. - * @param canvas an optional canvas to render the views to. If null, only the measure and - * layout steps will be executed. - */ - private static Result renderAndBuildResult(@NonNull ViewGroup viewRoot, @Nullable Canvas canvas) { - if (canvas == null) { - return SUCCESS.createResult(); - } - - AttachInfo_Accessor.dispatchOnPreDraw(viewRoot); - viewRoot.draw(canvas); - - return SUCCESS.createResult(); - } - - /** - * Renders the scene. - * <p> - * {@link #acquire(long)} must have been called before this. - * - * @param freshRender whether the render is a new one and should erase the existing bitmap (in - * the case where bitmaps are reused). This is typically needed when not playing - * animations.) - * - * @throws IllegalStateException if the current context is different than the one owned by - * the scene, or if {@link #acquire(long)} was not called. - * - * @see SessionParams#getRenderingMode() - * @see RenderSession#render(long) - */ - public Result render(boolean freshRender) { - return renderAndBuildResult(freshRender, false); - } - - /** - * Measures the layout - * <p> - * {@link #acquire(long)} must have been called before this. - * - * @throws IllegalStateException if the current context is different than the one owned by - * the scene, or if {@link #acquire(long)} was not called. - * - * @see SessionParams#getRenderingMode() - * @see RenderSession#render(long) - */ - public Result measure() { - return renderAndBuildResult(false, true); - } - - /** - * Renders the scene. - * <p> - * {@link #acquire(long)} must have been called before this. - * - * @param freshRender whether the render is a new one and should erase the existing bitmap (in - * the case where bitmaps are reused). This is typically needed when not playing - * animations.) - * - * @throws IllegalStateException if the current context is different than the one owned by - * the scene, or if {@link #acquire(long)} was not called. - * - * @see SessionParams#getRenderingMode() - * @see RenderSession#render(long) - */ - private Result renderAndBuildResult(boolean freshRender, boolean onlyMeasure) { - checkLock(); - - SessionParams params = getParams(); - - try { - if (mViewRoot == null) { - return ERROR_NOT_INFLATED.createResult(); - } - - measureLayout(params); - - HardwareConfig hardwareConfig = params.getHardwareConfig(); - Result renderResult = SUCCESS.createResult(); - if (onlyMeasure) { - // delete the canvas and image to reset them on the next full rendering - mImage = null; - mCanvas = null; - doLayout(getContext(), mViewRoot, mMeasuredScreenWidth, mMeasuredScreenHeight); - } else { - // draw the views - // create the BufferedImage into which the layout will be rendered. - boolean newImage = false; - - // When disableBitmapCaching is true, we do not reuse mImage and - // we create a new one in every render. - // This is useful when mImage is just a wrapper of Graphics2D so - // it doesn't get cached. - boolean disableBitmapCaching = Boolean.TRUE.equals(params.getFlag( - RenderParamsFlags.FLAG_KEY_DISABLE_BITMAP_CACHING)); - if (mNewRenderSize || mCanvas == null || disableBitmapCaching) { - mNewRenderSize = false; - if (params.getImageFactory() != null) { - mImage = params.getImageFactory().getImage( - mMeasuredScreenWidth, - mMeasuredScreenHeight); - } else { - mImage = new BufferedImage( - mMeasuredScreenWidth, - mMeasuredScreenHeight, - BufferedImage.TYPE_INT_ARGB); - newImage = true; - } - - if (params.isBgColorOverridden()) { - // since we override the content, it's the same as if it was a new image. - newImage = true; - Graphics2D gc = mImage.createGraphics(); - gc.setColor(new Color(params.getOverrideBgColor(), true)); - gc.setComposite(AlphaComposite.Src); - gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight); - gc.dispose(); - } - - // create an Android bitmap around the BufferedImage - Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage, - true /*isMutable*/, hardwareConfig.getDensity()); - - if (mCanvas == null) { - // create a Canvas around the Android bitmap - mCanvas = new Canvas(bitmap); - } else { - mCanvas.setBitmap(bitmap); - } - mCanvas.setDensity(hardwareConfig.getDensity().getDpiValue()); - } - - if (freshRender && !newImage) { - Graphics2D gc = mImage.createGraphics(); - gc.setComposite(AlphaComposite.Src); - - gc.setColor(new Color(0x00000000, true)); - gc.fillRect(0, 0, - mMeasuredScreenWidth, mMeasuredScreenHeight); - - // done - gc.dispose(); - } - - doLayout(getContext(), mViewRoot, mMeasuredScreenWidth, mMeasuredScreenHeight); - if (mElapsedFrameTimeNanos >= 0) { - long initialTime = System_Delegate.nanoTime(); - if (!mFirstFrameExecuted) { - // We need to run an initial draw call to initialize the animations - renderAndBuildResult(mViewRoot, NOP_CANVAS); - - // The first frame will initialize the animations - Choreographer_Delegate.doFrame(initialTime); - mFirstFrameExecuted = true; - } - // Second frame will move the animations - Choreographer_Delegate.doFrame(initialTime + mElapsedFrameTimeNanos); - } - renderResult = renderAndBuildResult(mViewRoot, mCanvas); - } - - mSystemViewInfoList = - visitAllChildren(mViewRoot, 0, 0, params.getExtendedViewInfoMode(), - false); - - // success! - return renderResult; - } catch (Throwable e) { - // get the real cause of the exception. - Throwable t = e; - while (t.getCause() != null) { - t = t.getCause(); - } - - return ERROR_UNKNOWN.createResult(t.getMessage(), t); - } - } - - /** - * Executes {@link View#measure(int, int)} on a given view with the given parameters (used - * to create measure specs with {@link MeasureSpec#makeMeasureSpec(int, int)}. - * - * if <var>measuredView</var> is non null, the method returns a {@link Pair} of (width, height) - * for the view (using {@link View#getMeasuredWidth()} and {@link View#getMeasuredHeight()}). - * - * @param viewToMeasure the view on which to execute measure(). - * @param measuredView if non null, the view to query for its measured width/height. - * @param width the width to use in the MeasureSpec. - * @param widthMode the MeasureSpec mode to use for the width. - * @param height the height to use in the MeasureSpec. - * @param heightMode the MeasureSpec mode to use for the height. - * @return the measured width/height if measuredView is non-null, null otherwise. - */ - @SuppressWarnings("deprecation") // For the use of Pair - private static Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView, - int width, int widthMode, int height, int heightMode) { - int w_spec = MeasureSpec.makeMeasureSpec(width, widthMode); - int h_spec = MeasureSpec.makeMeasureSpec(height, heightMode); - viewToMeasure.measure(w_spec, h_spec); - - if (measuredView != null) { - return Pair.of(measuredView.getMeasuredWidth(), measuredView.getMeasuredHeight()); - } - - return null; - } - - /** - * Animate an object - * <p> - * {@link #acquire(long)} must have been called before this. - * - * @throws IllegalStateException if the current context is different than the one owned by - * the scene, or if {@link #acquire(long)} was not called. - * - * @see RenderSession#animate(Object, String, boolean, IAnimationListener) - */ - public Result animate(Object targetObject, String animationName, - boolean isFrameworkAnimation, IAnimationListener listener) { - checkLock(); - - BridgeContext context = getContext(); - - // find the animation file. - ResourceValue animationResource; - int animationId = 0; - if (isFrameworkAnimation) { - animationResource = context.getRenderResources().getFrameworkResource( - ResourceType.ANIMATOR, animationName); - if (animationResource != null) { - animationId = Bridge.getResourceId(ResourceType.ANIMATOR, animationName); - } - } else { - animationResource = context.getRenderResources().getProjectResource( - ResourceType.ANIMATOR, animationName); - if (animationResource != null) { - animationId = context.getLayoutlibCallback().getResourceId( - ResourceType.ANIMATOR, animationName); - } - } - - if (animationResource != null) { - try { - Animator anim = AnimatorInflater.loadAnimator(context, animationId); - if (anim != null) { - anim.setTarget(targetObject); - - new PlayAnimationThread(anim, this, animationName, listener).start(); - - return SUCCESS.createResult(); - } - } catch (Exception e) { - // get the real cause of the exception. - Throwable t = e; - while (t.getCause() != null) { - t = t.getCause(); - } - - return ERROR_UNKNOWN.createResult(t.getMessage(), t); - } - } - - return ERROR_ANIM_NOT_FOUND.createResult(); - } - - /** - * Insert a new child into an existing parent. - * <p> - * {@link #acquire(long)} must have been called before this. - * - * @throws IllegalStateException if the current context is different than the one owned by - * the scene, or if {@link #acquire(long)} was not called. - * - * @see RenderSession#insertChild(Object, ILayoutPullParser, int, IAnimationListener) - */ - public Result insertChild(final ViewGroup parentView, ILayoutPullParser childXml, - final int index, IAnimationListener listener) { - checkLock(); - - BridgeContext context = getContext(); - - // create a block parser for the XML - BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser( - childXml, context, false /* platformResourceFlag */); - - // inflate the child without adding it to the root since we want to control where it'll - // get added. We do pass the parentView however to ensure that the layoutParams will - // be created correctly. - final View child = mInflater.inflate(blockParser, parentView, false /*attachToRoot*/); - blockParser.ensurePopped(); - - invalidateRenderingSize(); - - if (listener != null) { - new AnimationThread(this, "insertChild", listener) { - - @Override - public Result preAnimation() { - parentView.setLayoutTransition(new LayoutTransition()); - return addView(parentView, child, index); - } - - @Override - public void postAnimation() { - parentView.setLayoutTransition(null); - } - }.start(); - - // always return success since the real status will come through the listener. - return SUCCESS.createResult(child); - } - - // add it to the parentView in the correct location - Result result = addView(parentView, child, index); - if (!result.isSuccess()) { - return result; - } - - result = render(false /*freshRender*/); - if (result.isSuccess()) { - result = result.getCopyWithData(child); - } - - return result; - } - - /** - * Adds a given view to a given parent at a given index. - * - * @param parent the parent to receive the view - * @param view the view to add to the parent - * @param index the index where to do the add. - * - * @return a Result with {@link Status#SUCCESS} or - * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support - * adding views. - */ - private Result addView(ViewGroup parent, View view, int index) { - try { - parent.addView(view, index); - return SUCCESS.createResult(); - } catch (UnsupportedOperationException e) { - // looks like this is a view class that doesn't support children manipulation! - return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); - } - } - - /** - * Moves a view to a new parent at a given location - * <p> - * {@link #acquire(long)} must have been called before this. - * - * @throws IllegalStateException if the current context is different than the one owned by - * the scene, or if {@link #acquire(long)} was not called. - * - * @see RenderSession#moveChild(Object, Object, int, Map, IAnimationListener) - */ - public Result moveChild(final ViewGroup newParentView, final View childView, final int index, - Map<String, String> layoutParamsMap, final IAnimationListener listener) { - checkLock(); - - invalidateRenderingSize(); - - LayoutParams layoutParams = null; - if (layoutParamsMap != null) { - // need to create a new LayoutParams object for the new parent. - layoutParams = newParentView.generateLayoutParams( - new BridgeLayoutParamsMapAttributes(layoutParamsMap)); - } - - // get the current parent of the view that needs to be moved. - final ViewGroup previousParent = (ViewGroup) childView.getParent(); - - if (listener != null) { - final LayoutParams params = layoutParams; - - // there is no support for animating views across layouts, so in case the new and old - // parent views are different we fake the animation through a no animation thread. - if (previousParent != newParentView) { - new Thread("not animated moveChild") { - @Override - public void run() { - Result result = moveView(previousParent, newParentView, childView, index, - params); - if (!result.isSuccess()) { - listener.done(result); - } - - // ready to do the work, acquire the scene. - result = acquire(250); - if (!result.isSuccess()) { - listener.done(result); - return; - } - - try { - result = render(false /*freshRender*/); - if (result.isSuccess()) { - listener.onNewFrame(RenderSessionImpl.this.getSession()); - } - } finally { - release(); - } - - listener.done(result); - } - }.start(); - } else { - new AnimationThread(this, "moveChild", listener) { - - @Override - public Result preAnimation() { - // set up the transition for the parent. - LayoutTransition transition = new LayoutTransition(); - previousParent.setLayoutTransition(transition); - - // tweak the animation durations and start delays (to match the duration of - // animation playing just before). - // Note: Cannot user Animation.setDuration() directly. Have to set it - // on the LayoutTransition. - transition.setDuration(LayoutTransition.DISAPPEARING, 100); - // CHANGE_DISAPPEARING plays after DISAPPEARING - transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 100); - - transition.setDuration(LayoutTransition.CHANGE_DISAPPEARING, 100); - - transition.setDuration(LayoutTransition.CHANGE_APPEARING, 100); - // CHANGE_APPEARING plays after CHANGE_APPEARING - transition.setStartDelay(LayoutTransition.APPEARING, 100); - - transition.setDuration(LayoutTransition.APPEARING, 100); - - return moveView(previousParent, newParentView, childView, index, params); - } - - @Override - public void postAnimation() { - previousParent.setLayoutTransition(null); - newParentView.setLayoutTransition(null); - } - }.start(); - } - - // always return success since the real status will come through the listener. - return SUCCESS.createResult(layoutParams); - } - - Result result = moveView(previousParent, newParentView, childView, index, layoutParams); - if (!result.isSuccess()) { - return result; - } - - result = render(false /*freshRender*/); - if (layoutParams != null && result.isSuccess()) { - result = result.getCopyWithData(layoutParams); - } - - return result; - } - - /** - * Moves a View from its current parent to a new given parent at a new given location, with - * an optional new {@link LayoutParams} instance - * - * @param previousParent the previous parent, still owning the child at the time of the call. - * @param newParent the new parent - * @param movedView the view to move - * @param index the new location in the new parent - * @param params an option (can be null) {@link LayoutParams} instance. - * - * @return a Result with {@link Status#SUCCESS} or - * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support - * adding views. - */ - private Result moveView(ViewGroup previousParent, final ViewGroup newParent, - final View movedView, final int index, final LayoutParams params) { - try { - // check if there is a transition on the previousParent. - LayoutTransition previousTransition = previousParent.getLayoutTransition(); - if (previousTransition != null) { - // in this case there is an animation. This means we have to wait for the child's - // parent reference to be null'ed out so that we can add it to the new parent. - // It is technically removed right before the DISAPPEARING animation is done (if - // the animation of this type is not null, otherwise it's after which is impossible - // to handle). - // Because there is no move animation, if the new parent is the same as the old - // parent, we need to wait until the CHANGE_DISAPPEARING animation is done before - // adding the child or the child will appear in its new location before the - // other children have made room for it. - - // add a listener to the transition to be notified of the actual removal. - previousTransition.addTransitionListener(new TransitionListener() { - private int mChangeDisappearingCount = 0; - - @Override - public void startTransition(LayoutTransition transition, ViewGroup container, - View view, int transitionType) { - if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) { - mChangeDisappearingCount++; - } - } - - @Override - public void endTransition(LayoutTransition transition, ViewGroup container, - View view, int transitionType) { - if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) { - mChangeDisappearingCount--; - } - - if (transitionType == LayoutTransition.CHANGE_DISAPPEARING && - mChangeDisappearingCount == 0) { - // add it to the parentView in the correct location - if (params != null) { - newParent.addView(movedView, index, params); - } else { - newParent.addView(movedView, index); - } - } - } - }); - - // remove the view from the current parent. - previousParent.removeView(movedView); - - // and return since adding the view to the new parent is done in the listener. - return SUCCESS.createResult(); - } else { - // standard code with no animation. pretty simple. - previousParent.removeView(movedView); - - // add it to the parentView in the correct location - if (params != null) { - newParent.addView(movedView, index, params); - } else { - newParent.addView(movedView, index); - } - - return SUCCESS.createResult(); - } - } catch (UnsupportedOperationException e) { - // looks like this is a view class that doesn't support children manipulation! - return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); - } - } - - /** - * Removes a child from its current parent. - * <p> - * {@link #acquire(long)} must have been called before this. - * - * @throws IllegalStateException if the current context is different than the one owned by - * the scene, or if {@link #acquire(long)} was not called. - * - * @see RenderSession#removeChild(Object, IAnimationListener) - */ - public Result removeChild(final View childView, IAnimationListener listener) { - checkLock(); - - invalidateRenderingSize(); - - final ViewGroup parent = (ViewGroup) childView.getParent(); - - if (listener != null) { - new AnimationThread(this, "moveChild", listener) { - - @Override - public Result preAnimation() { - parent.setLayoutTransition(new LayoutTransition()); - return removeView(parent, childView); - } - - @Override - public void postAnimation() { - parent.setLayoutTransition(null); - } - }.start(); - - // always return success since the real status will come through the listener. - return SUCCESS.createResult(); - } - - Result result = removeView(parent, childView); - if (!result.isSuccess()) { - return result; - } - - return render(false /*freshRender*/); - } - - /** - * Removes a given view from its current parent. - * - * @param view the view to remove from its parent - * - * @return a Result with {@link Status#SUCCESS} or - * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support - * adding views. - */ - private Result removeView(ViewGroup parent, View view) { - try { - parent.removeView(view); - return SUCCESS.createResult(); - } catch (UnsupportedOperationException e) { - // looks like this is a view class that doesn't support children manipulation! - return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); - } - } - - /** - * Post process on a view hierarchy that was just inflated. - * <p/> - * At the moment this only supports TabHost: If {@link TabHost} is detected, look for the - * {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically - * based on the content of the {@link FrameLayout}. - * @param view the root view to process. - * @param layoutlibCallback callback to the project. - * @param skip the view and it's children are not processed. - */ - @SuppressWarnings("deprecation") // For the use of Pair - private void postInflateProcess(View view, LayoutlibCallback layoutlibCallback, View skip) - throws PostInflateException { - if (view == skip) { - return; - } - if (view instanceof TabHost) { - setupTabHost((TabHost) view, layoutlibCallback); - } else if (view instanceof QuickContactBadge) { - QuickContactBadge badge = (QuickContactBadge) view; - badge.setImageToDefault(); - } else if (view instanceof AdapterView<?>) { - // get the view ID. - int id = view.getId(); - - BridgeContext context = getContext(); - - // get a ResourceReference from the integer ID. - ResourceReference listRef = context.resolveId(id); - - if (listRef != null) { - SessionParams params = getParams(); - AdapterBinding binding = params.getAdapterBindings().get(listRef); - - // if there was no adapter binding, trying to get it from the call back. - if (binding == null) { - binding = layoutlibCallback.getAdapterBinding( - listRef, context.getViewKey(view), view); - } - - if (binding != null) { - - if (view instanceof AbsListView) { - if ((binding.getFooterCount() > 0 || binding.getHeaderCount() > 0) && - view instanceof ListView) { - ListView list = (ListView) view; - - boolean skipCallbackParser = false; - - int count = binding.getHeaderCount(); - for (int i = 0; i < count; i++) { - Pair<View, Boolean> pair = context.inflateView( - binding.getHeaderAt(i), - list, false, skipCallbackParser); - if (pair.getFirst() != null) { - list.addHeaderView(pair.getFirst()); - } - - skipCallbackParser |= pair.getSecond(); - } - - count = binding.getFooterCount(); - for (int i = 0; i < count; i++) { - Pair<View, Boolean> pair = context.inflateView( - binding.getFooterAt(i), - list, false, skipCallbackParser); - if (pair.getFirst() != null) { - list.addFooterView(pair.getFirst()); - } - - skipCallbackParser |= pair.getSecond(); - } - } - - if (view instanceof ExpandableListView) { - ((ExpandableListView) view).setAdapter( - new FakeExpandableAdapter(listRef, binding, layoutlibCallback)); - } else { - ((AbsListView) view).setAdapter( - new FakeAdapter(listRef, binding, layoutlibCallback)); - } - } else if (view instanceof AbsSpinner) { - ((AbsSpinner) view).setAdapter( - new FakeAdapter(listRef, binding, layoutlibCallback)); - } - } - } - } else if (view instanceof ViewGroup) { - mInflater.postInflateProcess(view); - ViewGroup group = (ViewGroup) view; - final int count = group.getChildCount(); - for (int c = 0; c < count; c++) { - View child = group.getChildAt(c); - postInflateProcess(child, layoutlibCallback, skip); - } - } - } - - /** - * If the root layout is a CoordinatorLayout with an AppBar: - * Set the title of the AppBar to the title of the activity context. - */ - private void setActiveToolbar(View view, BridgeContext context, SessionParams params) { - View coordinatorLayout = findChildView(view, DesignLibUtil.CN_COORDINATOR_LAYOUT); - if (coordinatorLayout == null) { - return; - } - View appBar = findChildView(coordinatorLayout, DesignLibUtil.CN_APPBAR_LAYOUT); - if (appBar == null) { - return; - } - ViewGroup collapsingToolbar = - (ViewGroup) findChildView(appBar, DesignLibUtil.CN_COLLAPSING_TOOLBAR_LAYOUT); - if (collapsingToolbar == null) { - return; - } - if (!hasToolbar(collapsingToolbar)) { - return; - } - RenderResources res = context.getRenderResources(); - String title = params.getAppLabel(); - ResourceValue titleValue = res.findResValue(title, false); - if (titleValue != null && titleValue.getValue() != null) { - title = titleValue.getValue(); - } - DesignLibUtil.setTitle(collapsingToolbar, title); - } - - private View findChildView(View view, String className) { - if (!(view instanceof ViewGroup)) { - return null; - } - ViewGroup group = (ViewGroup) view; - for (int i = 0; i < group.getChildCount(); i++) { - if (isInstanceOf(group.getChildAt(i), className)) { - return group.getChildAt(i); - } - } - return null; - } - - private boolean hasToolbar(View collapsingToolbar) { - if (!(collapsingToolbar instanceof ViewGroup)) { - return false; - } - ViewGroup group = (ViewGroup) collapsingToolbar; - for (int i = 0; i < group.getChildCount(); i++) { - if (isInstanceOf(group.getChildAt(i), DesignLibUtil.CN_TOOLBAR)) { - return true; - } - } - return false; - } - - /** - * Set the scroll position on all the components with the "scrollX" and "scrollY" attribute. If - * the component supports nested scrolling attempt that first, then use the unconsumed scroll - * part to scroll the content in the component. - */ - private static void handleScrolling(BridgeContext context, View view) { - int scrollPosX = context.getScrollXPos(view); - int scrollPosY = context.getScrollYPos(view); - if (scrollPosX != 0 || scrollPosY != 0) { - if (view.isNestedScrollingEnabled()) { - int[] consumed = new int[2]; - int axis = scrollPosX != 0 ? View.SCROLL_AXIS_HORIZONTAL : 0; - axis |= scrollPosY != 0 ? View.SCROLL_AXIS_VERTICAL : 0; - if (view.startNestedScroll(axis)) { - view.dispatchNestedPreScroll(scrollPosX, scrollPosY, consumed, null); - view.dispatchNestedScroll(consumed[0], consumed[1], scrollPosX, scrollPosY, - null); - view.stopNestedScroll(); - scrollPosX -= consumed[0]; - scrollPosY -= consumed[1]; - } - } - if (scrollPosX != 0 || scrollPosY != 0) { - view.scrollTo(scrollPosX, scrollPosY); - } - } - - if (!(view instanceof ViewGroup)) { - return; - } - ViewGroup group = (ViewGroup) view; - for (int i = 0; i < group.getChildCount(); i++) { - View child = group.getChildAt(i); - handleScrolling(context, child); - } - } - - /** - * Sets up a {@link TabHost} object. - * @param tabHost the TabHost to setup. - * @param layoutlibCallback The project callback object to access the project R class. - * @throws PostInflateException if TabHost is missing the required ids for TabHost - */ - private void setupTabHost(TabHost tabHost, LayoutlibCallback layoutlibCallback) - throws PostInflateException { - // look for the TabWidget, and the FrameLayout. They have their own specific names - View v = tabHost.findViewById(android.R.id.tabs); - - if (v == null) { - throw new PostInflateException( - "TabHost requires a TabWidget with id \"android:id/tabs\".\n"); - } - - if (!(v instanceof TabWidget)) { - throw new PostInflateException(String.format( - "TabHost requires a TabWidget with id \"android:id/tabs\".\n" + - "View found with id 'tabs' is '%s'", v.getClass().getCanonicalName())); - } - - v = tabHost.findViewById(android.R.id.tabcontent); - - if (v == null) { - // TODO: see if we can fake tabs even without the FrameLayout (same below when the frameLayout is empty) - //noinspection SpellCheckingInspection - throw new PostInflateException( - "TabHost requires a FrameLayout with id \"android:id/tabcontent\"."); - } - - if (!(v instanceof FrameLayout)) { - //noinspection SpellCheckingInspection - throw new PostInflateException(String.format( - "TabHost requires a FrameLayout with id \"android:id/tabcontent\".\n" + - "View found with id 'tabcontent' is '%s'", v.getClass().getCanonicalName())); - } - - FrameLayout content = (FrameLayout)v; - - // now process the content of the frameLayout and dynamically create tabs for it. - final int count = content.getChildCount(); - - // this must be called before addTab() so that the TabHost searches its TabWidget - // and FrameLayout. - tabHost.setup(); - - if (count == 0) { - // Create a dummy child to get a single tab - TabSpec spec = tabHost.newTabSpec("tag") - .setIndicator("Tab Label", tabHost.getResources() - .getDrawable(android.R.drawable.ic_menu_info_details, null)) - .setContent(tag -> new LinearLayout(getContext())); - tabHost.addTab(spec); - } else { - // for each child of the frameLayout, add a new TabSpec - for (int i = 0 ; i < count ; i++) { - View child = content.getChildAt(i); - String tabSpec = String.format("tab_spec%d", i+1); - @SuppressWarnings("ConstantConditions") // child cannot be null. - int id = child.getId(); - @SuppressWarnings("deprecation") - Pair<ResourceType, String> resource = layoutlibCallback.resolveResourceId(id); - String name; - if (resource != null) { - name = resource.getSecond(); - } else { - name = String.format("Tab %d", i+1); // default name if id is unresolved. - } - tabHost.addTab(tabHost.newTabSpec(tabSpec).setIndicator(name).setContent(id)); - } - } - } - - /** - * Visits a {@link View} and its children and generate a {@link ViewInfo} containing the - * bounds of all the views. - * - * @param view the root View - * @param hOffset horizontal offset for the view bounds. - * @param vOffset vertical offset for the view bounds. - * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object. - * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the - * content frame. - * - * @return {@code ViewInfo} containing the bounds of the view and it children otherwise. - */ - private ViewInfo visit(View view, int hOffset, int vOffset, boolean setExtendedInfo, - boolean isContentFrame) { - ViewInfo result = createViewInfo(view, hOffset, vOffset, setExtendedInfo, isContentFrame); - - if (view instanceof ViewGroup) { - ViewGroup group = ((ViewGroup) view); - result.setChildren(visitAllChildren(group, isContentFrame ? 0 : hOffset, - isContentFrame ? 0 : vOffset, - setExtendedInfo, isContentFrame)); - } - return result; - } - - /** - * Visits all the children of a given ViewGroup and generates a list of {@link ViewInfo} - * containing the bounds of all the views. It also initializes the {@link #mViewInfoList} with - * the children of the {@code mContentRoot}. - * - * @param viewGroup the root View - * @param hOffset horizontal offset from the top for the content view frame. - * @param vOffset vertical offset from the top for the content view frame. - * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object. - * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the - * content frame. {@code false} if the {@code ViewInfo} to be created is - * part of the system decor. - */ - private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int hOffset, int vOffset, - boolean setExtendedInfo, boolean isContentFrame) { - if (viewGroup == null) { - return null; - } - - if (!isContentFrame) { - vOffset += viewGroup.getTop(); - hOffset += viewGroup.getLeft(); - } - - int childCount = viewGroup.getChildCount(); - if (viewGroup == mContentRoot) { - List<ViewInfo> childrenWithoutOffset = new ArrayList<>(childCount); - List<ViewInfo> childrenWithOffset = new ArrayList<>(childCount); - for (int i = 0; i < childCount; i++) { - ViewInfo[] childViewInfo = - visitContentRoot(viewGroup.getChildAt(i), hOffset, vOffset, - setExtendedInfo); - childrenWithoutOffset.add(childViewInfo[0]); - childrenWithOffset.add(childViewInfo[1]); - } - mViewInfoList = childrenWithOffset; - return childrenWithoutOffset; - } else { - List<ViewInfo> children = new ArrayList<>(childCount); - for (int i = 0; i < childCount; i++) { - children.add(visit(viewGroup.getChildAt(i), hOffset, vOffset, setExtendedInfo, - isContentFrame)); - } - return children; - } - } - - /** - * Visits the children of {@link #mContentRoot} and generates {@link ViewInfo} containing the - * bounds of all the views. It returns two {@code ViewInfo} objects with the same children, - * one with the {@code offset} and other without the {@code offset}. The offset is needed to - * get the right bounds if the {@code ViewInfo} hierarchy is accessed from - * {@code mViewInfoList}. When the hierarchy is accessed via {@code mSystemViewInfoList}, the - * offset is not needed. - * - * @return an array of length two, with ViewInfo at index 0 is without offset and ViewInfo at - * index 1 is with the offset. - */ - @NonNull - private ViewInfo[] visitContentRoot(View view, int hOffset, int vOffset, - boolean setExtendedInfo) { - ViewInfo[] result = new ViewInfo[2]; - if (view == null) { - return result; - } - - result[0] = createViewInfo(view, 0, 0, setExtendedInfo, true); - result[1] = createViewInfo(view, hOffset, vOffset, setExtendedInfo, true); - if (view instanceof ViewGroup) { - List<ViewInfo> children = - visitAllChildren((ViewGroup) view, 0, 0, setExtendedInfo, true); - result[0].setChildren(children); - result[1].setChildren(children); - } - return result; - } - - /** - * Creates a {@link ViewInfo} for the view. The {@code ViewInfo} corresponding to the children - * of the {@code view} are not created. Consequently, the children of {@code ViewInfo} is not - * set. - * @param hOffset horizontal offset for the view bounds. Used only if view is part of the - * content frame. - * @param vOffset vertial an offset for the view bounds. Used only if view is part of the - * content frame. - */ - private ViewInfo createViewInfo(View view, int hOffset, int vOffset, boolean setExtendedInfo, - boolean isContentFrame) { - if (view == null) { - return null; - } - - ViewParent parent = view.getParent(); - ViewInfo result; - if (isContentFrame) { - // Account for parent scroll values when calculating the bounding box - int scrollX = parent != null ? ((View)parent).getScrollX() : 0; - int scrollY = parent != null ? ((View)parent).getScrollY() : 0; - - // The view is part of the layout added by the user. Hence, - // the ViewCookie may be obtained only through the Context. - result = new ViewInfo(view.getClass().getName(), - getContext().getViewKey(view), -scrollX + view.getLeft() + hOffset, - -scrollY + view.getTop() + vOffset, -scrollX + view.getRight() + hOffset, - -scrollY + view.getBottom() + vOffset, - view, view.getLayoutParams()); - } else { - // We are part of the system decor. - SystemViewInfo r = new SystemViewInfo(view.getClass().getName(), - getViewKey(view), - view.getLeft(), view.getTop(), view.getRight(), - view.getBottom(), view, view.getLayoutParams()); - result = r; - // We currently mark three kinds of views: - // 1. Menus in the Action Bar - // 2. Menus in the Overflow popup. - // 3. The overflow popup button. - if (view instanceof ListMenuItemView) { - // Mark 2. - // All menus in the popup are of type ListMenuItemView. - r.setViewType(ViewType.ACTION_BAR_OVERFLOW_MENU); - } else { - // Mark 3. - ViewGroup.LayoutParams lp = view.getLayoutParams(); - if (lp instanceof ActionMenuView.LayoutParams && - ((ActionMenuView.LayoutParams) lp).isOverflowButton) { - r.setViewType(ViewType.ACTION_BAR_OVERFLOW); - } else { - // Mark 1. - // A view is a menu in the Action Bar is it is not the overflow button and of - // its parent is of type ActionMenuView. We can also check if the view is - // instanceof ActionMenuItemView but that will fail for menus using - // actionProviderClass. - while (parent != mViewRoot && parent instanceof ViewGroup) { - if (parent instanceof ActionMenuView) { - r.setViewType(ViewType.ACTION_BAR_MENU); - break; - } - parent = parent.getParent(); - } - } - } - } - - if (setExtendedInfo) { - MarginLayoutParams marginParams = null; - LayoutParams params = view.getLayoutParams(); - if (params instanceof MarginLayoutParams) { - marginParams = (MarginLayoutParams) params; - } - result.setExtendedInfo(view.getBaseline(), - marginParams != null ? marginParams.leftMargin : 0, - marginParams != null ? marginParams.topMargin : 0, - marginParams != null ? marginParams.rightMargin : 0, - marginParams != null ? marginParams.bottomMargin : 0); - } - - return result; - } - - /* (non-Javadoc) - * The cookie for menu items are stored in menu item and not in the map from View stored in - * BridgeContext. - */ - @Nullable - private Object getViewKey(View view) { - BridgeContext context = getContext(); - if (!(view instanceof MenuView.ItemView)) { - return context.getViewKey(view); - } - MenuItemImpl menuItem; - if (view instanceof ActionMenuItemView) { - menuItem = ((ActionMenuItemView) view).getItemData(); - } else if (view instanceof ListMenuItemView) { - menuItem = ((ListMenuItemView) view).getItemData(); - } else if (view instanceof IconMenuItemView) { - menuItem = ((IconMenuItemView) view).getItemData(); - } else { - menuItem = null; - } - if (menuItem instanceof BridgeMenuItemImpl) { - return ((BridgeMenuItemImpl) menuItem).getViewCookie(); - } - - return null; - } - - public void invalidateRenderingSize() { - mMeasuredScreenWidth = mMeasuredScreenHeight = -1; - } - - public BufferedImage getImage() { - return mImage; - } - - public boolean isAlphaChannelImage() { - return mIsAlphaChannelImage; - } - - public List<ViewInfo> getViewInfos() { - return mViewInfoList; - } - - public List<ViewInfo> getSystemViewInfos() { - return mSystemViewInfoList; - } - - public Map<Object, PropertiesMap> getDefaultProperties() { - return getContext().getDefaultProperties(); - } - - public void setScene(RenderSession session) { - mScene = session; - } - - public RenderSession getSession() { - return mScene; - } - - public void dispose() { - boolean createdLooper = false; - if (Looper.myLooper() == null) { - // Detaching the root view from the window will try to stop any running animations. - // The stop method checks that it can run in the looper so, if there is no current - // looper, we create a temporary one to complete the shutdown. - Bridge.prepareThread(); - createdLooper = true; - } - AttachInfo_Accessor.detachFromWindow(mViewRoot); - if (mCanvas != null) { - mCanvas.release(); - mCanvas = null; - } - if (mViewInfoList != null) { - mViewInfoList.clear(); - } - if (mSystemViewInfoList != null) { - mSystemViewInfoList.clear(); - } - mImage = null; - mViewRoot = null; - mContentRoot = null; - - if (createdLooper) { - Bridge.cleanupThread(); - Choreographer_Delegate.dispose(); - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java deleted file mode 100644 index 75f9ec527e63..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java +++ /dev/null @@ -1,706 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.impl; - -import com.android.SdkConstants; -import com.android.ide.common.rendering.api.DensityBasedResourceValue; -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.internal.util.XmlUtils; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; -import com.android.layoutlib.bridge.android.RenderParamsFlags; -import com.android.ninepatch.NinePatch; -import com.android.ninepatch.NinePatchChunk; -import com.android.resources.Density; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.res.ColorStateList; -import android.content.res.ComplexColor; -import android.content.res.ComplexColor_Accessor; -import android.content.res.FontResourcesParser; -import android.content.res.GradientColor; -import android.content.res.Resources.Theme; -import android.graphics.Bitmap; -import android.graphics.Bitmap_Delegate; -import android.graphics.Color; -import android.graphics.NinePatch_Delegate; -import android.graphics.Rect; -import android.graphics.Typeface; -import android.graphics.Typeface_Accessor; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.ColorDrawable; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.NinePatchDrawable; -import android.text.FontConfig; -import android.util.TypedValue; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Helper class to provide various conversion method used in handling android resources. - */ -public final class ResourceHelper { - - private final static Pattern sFloatPattern = Pattern.compile("(-?[0-9]+(?:\\.[0-9]+)?)(.*)"); - private final static float[] sFloatOut = new float[1]; - - private final static TypedValue mValue = new TypedValue(); - - /** - * Returns the color value represented by the given string value - * @param value the color value - * @return the color as an int - * @throws NumberFormatException if the conversion failed. - */ - public static int getColor(String value) { - if (value != null) { - value = value.trim(); - if (!value.startsWith("#")) { - if (value.startsWith(SdkConstants.PREFIX_THEME_REF)) { - throw new NumberFormatException(String.format( - "Attribute '%s' not found. Are you using the right theme?", value)); - } - throw new NumberFormatException( - String.format("Color value '%s' must start with #", value)); - } - - value = value.substring(1); - - // make sure it's not longer than 32bit - if (value.length() > 8) { - throw new NumberFormatException(String.format( - "Color value '%s' is too long. Format is either" + - "#AARRGGBB, #RRGGBB, #RGB, or #ARGB", - value)); - } - - if (value.length() == 3) { // RGB format - char[] color = new char[8]; - color[0] = color[1] = 'F'; - color[2] = color[3] = value.charAt(0); - color[4] = color[5] = value.charAt(1); - color[6] = color[7] = value.charAt(2); - value = new String(color); - } else if (value.length() == 4) { // ARGB format - char[] color = new char[8]; - color[0] = color[1] = value.charAt(0); - color[2] = color[3] = value.charAt(1); - color[4] = color[5] = value.charAt(2); - color[6] = color[7] = value.charAt(3); - value = new String(color); - } else if (value.length() == 6) { - value = "FF" + value; - } - - // this is a RRGGBB or AARRGGBB value - - // Integer.parseInt will fail to parse strings like "ff191919", so we use - // a Long, but cast the result back into an int, since we know that we're only - // dealing with 32 bit values. - return (int)Long.parseLong(value, 16); - } - - throw new NumberFormatException(); - } - - /** - * Returns a {@link ComplexColor} from the given {@link ResourceValue} - * - * @param resValue the value containing a color value or a file path to a complex color - * definition - * @param context the current context - * @param theme the theme to use when resolving the complex color - * @param allowGradients when false, only {@link ColorStateList} will be returned. If a {@link - * GradientColor} is found, null will be returned. - */ - @Nullable - private static ComplexColor getInternalComplexColor(@NonNull ResourceValue resValue, - @NonNull BridgeContext context, @Nullable Theme theme, boolean allowGradients) { - String value = resValue.getValue(); - if (value == null || RenderResources.REFERENCE_NULL.equals(value)) { - return null; - } - - XmlPullParser parser = null; - // first check if the value is a file (xml most likely) - Boolean psiParserSupport = context.getLayoutlibCallback().getFlag( - RenderParamsFlags.FLAG_KEY_XML_FILE_PARSER_SUPPORT); - if (psiParserSupport != null && psiParserSupport) { - parser = context.getLayoutlibCallback().getXmlFileParser(value); - } - if (parser == null) { - File f = new File(value); - if (f.isFile()) { - // let the framework inflate the color from the XML file, by - // providing an XmlPullParser - try { - parser = ParserFactory.create(f); - } catch (XmlPullParserException | FileNotFoundException e) { - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ, - "Failed to parse file " + value, e, null /*data*/); - } - } - } - - if (parser != null) { - try { - BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser( - parser, context, resValue.isFramework()); - try { - // Advance the parser to the first element so we can detect if it's a - // color list or a gradient color - int type; - //noinspection StatementWithEmptyBody - while ((type = blockParser.next()) != XmlPullParser.START_TAG - && type != XmlPullParser.END_DOCUMENT) { - // Seek parser to start tag. - } - - if (type != XmlPullParser.START_TAG) { - assert false : "No start tag found"; - return null; - } - - final String name = blockParser.getName(); - if (allowGradients && "gradient".equals(name)) { - return ComplexColor_Accessor.createGradientColorFromXmlInner( - context.getResources(), - blockParser, blockParser, - theme); - } else if ("selector".equals(name)) { - return ComplexColor_Accessor.createColorStateListFromXmlInner( - context.getResources(), - blockParser, blockParser, - theme); - } - } finally { - blockParser.ensurePopped(); - } - } catch (XmlPullParserException e) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "Failed to configure parser for " + value, e, null /*data*/); - // we'll return null below. - } catch (Exception e) { - // this is an error and not warning since the file existence is - // checked before attempting to parse it. - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ, - "Failed to parse file " + value, e, null /*data*/); - - return null; - } - } else { - // try to load the color state list from an int - try { - int color = getColor(value); - return ColorStateList.valueOf(color); - } catch (NumberFormatException e) { - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, - "Failed to convert " + value + " into a ColorStateList", e, - null /*data*/); - } - } - - return null; - } - - /** - * Returns a {@link ColorStateList} from the given {@link ResourceValue} - * - * @param resValue the value containing a color value or a file path to a complex color - * definition - * @param context the current context - */ - @Nullable - public static ColorStateList getColorStateList(@NonNull ResourceValue resValue, - @NonNull BridgeContext context) { - return (ColorStateList) getInternalComplexColor(resValue, context, context.getTheme(), - false); - } - - /** - * Returns a {@link ComplexColor} from the given {@link ResourceValue} - * - * @param resValue the value containing a color value or a file path to a complex color - * definition - * @param context the current context - */ - @Nullable - public static ComplexColor getComplexColor(@NonNull ResourceValue resValue, - @NonNull BridgeContext context) { - return getInternalComplexColor(resValue, context, context.getTheme(), true); - } - - /** - * Returns a drawable from the given value. - * @param value The value that contains a path to a 9 patch, a bitmap or a xml based drawable, - * or an hexadecimal color - * @param context the current context - */ - public static Drawable getDrawable(ResourceValue value, BridgeContext context) { - return getDrawable(value, context, null); - } - - /** - * Returns a drawable from the given value. - * @param value The value that contains a path to a 9 patch, a bitmap or a xml based drawable, - * or an hexadecimal color - * @param context the current context - * @param theme the theme to be used to inflate the drawable. - */ - public static Drawable getDrawable(ResourceValue value, BridgeContext context, Theme theme) { - if (value == null) { - return null; - } - String stringValue = value.getValue(); - if (RenderResources.REFERENCE_NULL.equals(stringValue)) { - return null; - } - - String lowerCaseValue = stringValue.toLowerCase(); - - Density density = Density.MEDIUM; - if (value instanceof DensityBasedResourceValue) { - density = ((DensityBasedResourceValue) value).getResourceDensity(); - } - - if (lowerCaseValue.endsWith(NinePatch.EXTENSION_9PATCH)) { - File file = new File(stringValue); - if (file.isFile()) { - try { - return getNinePatchDrawable(new FileInputStream(file), density, - value.isFramework(), stringValue, context); - } catch (IOException e) { - // failed to read the file, we'll return null below. - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ, - "Failed lot load " + file.getAbsolutePath(), e, null /*data*/); - } - } - - return null; - } else if (lowerCaseValue.endsWith(".xml") || stringValue.startsWith("@aapt:_aapt/")) { - // create a block parser for the file - try { - XmlPullParser parser = context.getLayoutlibCallback().getParser(value); - if (parser == null) { - File drawableFile = new File(stringValue); - if (drawableFile.isFile()) { - parser = ParserFactory.create(drawableFile); - } - } - - BridgeXmlBlockParser blockParser = - new BridgeXmlBlockParser(parser, context, value.isFramework()); - try { - return Drawable.createFromXml(context.getResources(), blockParser, theme); - } finally { - blockParser.ensurePopped(); - } - } catch (Exception e) { - // this is an error and not warning since the file existence is checked before - // attempting to parse it. - Bridge.getLog().error(null, "Failed to parse file " + stringValue, e, - null /*data*/); - } - - return null; - } else { - File bmpFile = new File(stringValue); - if (bmpFile.isFile()) { - try { - Bitmap bitmap = Bridge.getCachedBitmap(stringValue, - value.isFramework() ? null : context.getProjectKey()); - - if (bitmap == null) { - bitmap = - Bitmap_Delegate.createBitmap(bmpFile, false /*isMutable*/, density); - Bridge.setCachedBitmap(stringValue, bitmap, - value.isFramework() ? null : context.getProjectKey()); - } - - return new BitmapDrawable(context.getResources(), bitmap); - } catch (IOException e) { - // we'll return null below - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ, - "Failed lot load " + bmpFile.getAbsolutePath(), e, null /*data*/); - } - } else { - // attempt to get a color from the value - try { - int color = getColor(stringValue); - return new ColorDrawable(color); - } catch (NumberFormatException e) { - // we'll return null below. - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, - "Failed to convert " + stringValue + " into a drawable", e, - null /*data*/); - } - } - } - - return null; - } - - /** - * Returns a {@link Typeface} given a font name. The font name, can be a system font family - * (like sans-serif) or a full path if the font is to be loaded from resources. - */ - public static Typeface getFont(String fontName, BridgeContext context, Theme theme, boolean - isFramework) { - if (fontName == null) { - return null; - } - - if (Typeface_Accessor.isSystemFont(fontName)) { - // Shortcut for the case where we are asking for a system font name. Those are not - // loaded using external resources. - return null; - } - - // Check if this is an asset that we've already loaded dynamically - Typeface typeface = Typeface.findFromCache(context.getAssets(), fontName); - if (typeface != null) { - return typeface; - } - - String lowerCaseValue = fontName.toLowerCase(); - if (lowerCaseValue.endsWith(".xml")) { - // create a block parser for the file - Boolean psiParserSupport = context.getLayoutlibCallback().getFlag( - RenderParamsFlags.FLAG_KEY_XML_FILE_PARSER_SUPPORT); - XmlPullParser parser = null; - if (psiParserSupport != null && psiParserSupport) { - parser = context.getLayoutlibCallback().getXmlFileParser(fontName); - } - else { - File f = new File(fontName); - if (f.isFile()) { - try { - parser = ParserFactory.create(f); - } catch (XmlPullParserException | FileNotFoundException e) { - // this is an error and not warning since the file existence is checked before - // attempting to parse it. - Bridge.getLog().error(null, "Failed to parse file " + fontName, - e, null /*data*/); - } - } - } - - if (parser != null) { - BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser( - parser, context, isFramework); - try { - FontResourcesParser.FamilyResourceEntry entry = - FontResourcesParser.parse(blockParser, context.getResources()); - typeface = Typeface.createFromResources(entry, context.getAssets(), - fontName); - } catch (XmlPullParserException | IOException e) { - Bridge.getLog().error(null, "Failed to parse file " + fontName, - e, null /*data*/); - } finally { - blockParser.ensurePopped(); - } - } else { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - String.format("File %s does not exist (or is not a file)", fontName), - null /*data*/); - } - } else { - typeface = Typeface.createFromResources(context.getAssets(), fontName, 0); - } - - return typeface; - } - - /** - * Returns a {@link Typeface} given a font name. The font name, can be a system font family - * (like sans-serif) or a full path if the font is to be loaded from resources. - */ - public static Typeface getFont(ResourceValue value, BridgeContext context, Theme theme) { - if (value == null) { - return null; - } - - return getFont(value.getValue(), context, theme, value.isFramework()); - } - - private static Drawable getNinePatchDrawable(InputStream inputStream, Density density, - boolean isFramework, String cacheKey, BridgeContext context) throws IOException { - // see if we still have both the chunk and the bitmap in the caches - NinePatchChunk chunk = Bridge.getCached9Patch(cacheKey, - isFramework ? null : context.getProjectKey()); - Bitmap bitmap = Bridge.getCachedBitmap(cacheKey, - isFramework ? null : context.getProjectKey()); - - // if either chunk or bitmap is null, then we reload the 9-patch file. - if (chunk == null || bitmap == null) { - try { - NinePatch ninePatch = NinePatch.load(inputStream, true /*is9Patch*/, - false /* convert */); - if (ninePatch != null) { - if (chunk == null) { - chunk = ninePatch.getChunk(); - - Bridge.setCached9Patch(cacheKey, chunk, - isFramework ? null : context.getProjectKey()); - } - - if (bitmap == null) { - bitmap = Bitmap_Delegate.createBitmap(ninePatch.getImage(), - false /*isMutable*/, - density); - - Bridge.setCachedBitmap(cacheKey, bitmap, - isFramework ? null : context.getProjectKey()); - } - } - } catch (MalformedURLException e) { - // URL is wrong, we'll return null below - } - } - - if (chunk != null && bitmap != null) { - int[] padding = chunk.getPadding(); - Rect paddingRect = new Rect(padding[0], padding[1], padding[2], padding[3]); - - return new NinePatchDrawable(context.getResources(), bitmap, - NinePatch_Delegate.serialize(chunk), - paddingRect, null); - } - - return null; - } - - /** - * Looks for an attribute in the current theme. - * - * @param resources the render resources - * @param name the name of the attribute - * @param defaultValue the default value. - * @param isFrameworkAttr if the attribute is in android namespace - * @return the value of the attribute or the default one if not found. - */ - public static boolean getBooleanThemeValue(@NonNull RenderResources resources, String name, - boolean isFrameworkAttr, boolean defaultValue) { - ResourceValue value = resources.findItemInTheme(name, isFrameworkAttr); - value = resources.resolveResValue(value); - if (value == null) { - return defaultValue; - } - return XmlUtils.convertValueToBoolean(value.getValue(), defaultValue); - } - - // ------- TypedValue stuff - // This is taken from //device/libs/utils/ResourceTypes.cpp - - private static final class UnitEntry { - String name; - int type; - int unit; - float scale; - - UnitEntry(String name, int type, int unit, float scale) { - this.name = name; - this.type = type; - this.unit = unit; - this.scale = scale; - } - } - - private final static UnitEntry[] sUnitNames = new UnitEntry[] { - new UnitEntry("px", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_PX, 1.0f), - new UnitEntry("dip", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_DIP, 1.0f), - new UnitEntry("dp", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_DIP, 1.0f), - new UnitEntry("sp", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_SP, 1.0f), - new UnitEntry("pt", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_PT, 1.0f), - new UnitEntry("in", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_IN, 1.0f), - new UnitEntry("mm", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_MM, 1.0f), - new UnitEntry("%", TypedValue.TYPE_FRACTION, TypedValue.COMPLEX_UNIT_FRACTION, 1.0f/100), - new UnitEntry("%p", TypedValue.TYPE_FRACTION, TypedValue.COMPLEX_UNIT_FRACTION_PARENT, 1.0f/100), - }; - - /** - * Returns the raw value from the given attribute float-type value string. - * This object is only valid until the next call on to {@link ResourceHelper}. - */ - public static TypedValue getValue(String attribute, String value, boolean requireUnit) { - if (parseFloatAttribute(attribute, value, mValue, requireUnit)) { - return mValue; - } - - return null; - } - - /** - * Parse a float attribute and return the parsed value into a given TypedValue. - * @param attribute the name of the attribute. Can be null if <var>requireUnit</var> is false. - * @param value the string value of the attribute - * @param outValue the TypedValue to receive the parsed value - * @param requireUnit whether the value is expected to contain a unit. - * @return true if success. - */ - public static boolean parseFloatAttribute(String attribute, @NonNull String value, - TypedValue outValue, boolean requireUnit) { - assert !requireUnit || attribute != null; - - // remove the space before and after - value = value.trim(); - int len = value.length(); - - if (len <= 0) { - return false; - } - - // check that there's no non ascii characters. - char[] buf = value.toCharArray(); - for (int i = 0 ; i < len ; i++) { - if (buf[i] > 255) { - return false; - } - } - - // check the first character - if ((buf[0] < '0' || buf[0] > '9') && buf[0] != '.' && buf[0] != '-' && buf[0] != '+') { - return false; - } - - // now look for the string that is after the float... - Matcher m = sFloatPattern.matcher(value); - if (m.matches()) { - String f_str = m.group(1); - String end = m.group(2); - - float f; - try { - f = Float.parseFloat(f_str); - } catch (NumberFormatException e) { - // this shouldn't happen with the regexp above. - return false; - } - - if (end.length() > 0 && end.charAt(0) != ' ') { - // Might be a unit... - if (parseUnit(end, outValue, sFloatOut)) { - computeTypedValue(outValue, f, sFloatOut[0]); - return true; - } - return false; - } - - // make sure it's only spaces at the end. - end = end.trim(); - - if (end.length() == 0) { - if (outValue != null) { - if (!requireUnit) { - outValue.type = TypedValue.TYPE_FLOAT; - outValue.data = Float.floatToIntBits(f); - } else { - // no unit when required? Use dp and out an error. - applyUnit(sUnitNames[1], outValue, sFloatOut); - computeTypedValue(outValue, f, sFloatOut[0]); - - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE, - String.format( - "Dimension \"%1$s\" in attribute \"%2$s\" is missing unit!", - value, attribute), - null); - } - return true; - } - } - } - - return false; - } - - private static void computeTypedValue(TypedValue outValue, float value, float scale) { - value *= scale; - boolean neg = value < 0; - if (neg) { - value = -value; - } - long bits = (long)(value*(1<<23)+.5f); - int radix; - int shift; - if ((bits&0x7fffff) == 0) { - // Always use 23p0 if there is no fraction, just to make - // things easier to read. - radix = TypedValue.COMPLEX_RADIX_23p0; - shift = 23; - } else if ((bits&0xffffffffff800000L) == 0) { - // Magnitude is zero -- can fit in 0 bits of precision. - radix = TypedValue.COMPLEX_RADIX_0p23; - shift = 0; - } else if ((bits&0xffffffff80000000L) == 0) { - // Magnitude can fit in 8 bits of precision. - radix = TypedValue.COMPLEX_RADIX_8p15; - shift = 8; - } else if ((bits&0xffffff8000000000L) == 0) { - // Magnitude can fit in 16 bits of precision. - radix = TypedValue.COMPLEX_RADIX_16p7; - shift = 16; - } else { - // Magnitude needs entire range, so no fractional part. - radix = TypedValue.COMPLEX_RADIX_23p0; - shift = 23; - } - int mantissa = (int)( - (bits>>shift) & TypedValue.COMPLEX_MANTISSA_MASK); - if (neg) { - mantissa = (-mantissa) & TypedValue.COMPLEX_MANTISSA_MASK; - } - outValue.data |= - (radix<<TypedValue.COMPLEX_RADIX_SHIFT) - | (mantissa<<TypedValue.COMPLEX_MANTISSA_SHIFT); - } - - private static boolean parseUnit(String str, TypedValue outValue, float[] outScale) { - str = str.trim(); - - for (UnitEntry unit : sUnitNames) { - if (unit.name.equals(str)) { - applyUnit(unit, outValue, outScale); - return true; - } - } - - return false; - } - - private static void applyUnit(UnitEntry unit, TypedValue outValue, float[] outScale) { - outValue.type = unit.type; - // COMPLEX_UNIT_SHIFT is 0 and hence intelliJ complains about it. Suppress the warning. - //noinspection PointlessBitwiseExpression - outValue.data = unit.unit << TypedValue.COMPLEX_UNIT_SHIFT; - outScale[0] = unit.scale; - } -} - diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Stack.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Stack.java deleted file mode 100644 index 9bd0015db508..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Stack.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.impl; - -import java.util.ArrayList; - -/** - * Custom Stack implementation on top of an {@link ArrayList} instead of - * using {@link java.util.Stack} which is on top of a vector. - * - * @param <T> - */ -public class Stack<T> extends ArrayList<T> { - - private static final long serialVersionUID = 1L; - - public Stack() { - super(); - } - - public Stack(int size) { - super(size); - } - - /** - * Pushes the given object to the stack - * @param object the object to push - */ - public void push(T object) { - add(object); - } - - /** - * Remove the object at the top of the stack and returns it. - * @return the removed object or null if the stack was empty. - */ - public T pop() { - if (size() > 0) { - return remove(size() - 1); - } - - return null; - } - - /** - * Returns the object at the top of the stack. - * @return the object at the top or null if the stack is empty. - */ - public T peek() { - if (size() > 0) { - return get(size() - 1); - } - - return null; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/SystemViewInfo.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/SystemViewInfo.java deleted file mode 100644 index 9fea1677d5f2..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/SystemViewInfo.java +++ /dev/null @@ -1,51 +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 com.android.layoutlib.bridge.impl; - -import com.android.ide.common.rendering.api.ViewInfo; -import com.android.ide.common.rendering.api.ViewType; - -/** - * ViewInfo for views added by the platform. - */ -public class SystemViewInfo extends ViewInfo { - - private ViewType mViewType; - - public SystemViewInfo(String name, Object cookie, int left, int top, - int right, int bottom) { - super(name, cookie, left, top, right, bottom); - } - - public SystemViewInfo(String name, Object cookie, int left, int top, - int right, int bottom, Object viewObject, Object layoutParamsObject) { - super(name, cookie, left, top, right, bottom, viewObject, - layoutParamsObject); - } - - @Override - public ViewType getViewType() { - if (mViewType != null) { - return mViewType; - } - return ViewType.SYSTEM_UNKNOWN; - } - - public void setViewType(ViewType type) { - mViewType = type; - } -} 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 deleted file mode 100644 index c0ca1d5916e9..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterHelper.java +++ /dev/null @@ -1,148 +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 com.android.layoutlib.bridge.impl.binding; - -import com.android.ide.common.rendering.api.DataBindingItem; -import com.android.ide.common.rendering.api.LayoutlibCallback; -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.ide.common.rendering.api.ResourceReference; -import com.android.ide.common.rendering.api.IProjectCallback.ViewAttribute; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.impl.RenderAction; -import com.android.util.Pair; - -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.Checkable; -import android.widget.ImageView; -import android.widget.TextView; - -/** - * A Helper class to do fake data binding in {@link AdapterView} objects. - */ -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. - DataBindingItem dataBindingItem = item.getDataBindingItem(); - - BridgeContext context = RenderAction.getCurrentContext(); - - Pair<View, Boolean> pair = context.inflateView(dataBindingItem.getViewReference(), - parent, false /*attachToRoot*/, skipCallbackParser); - - View view = pair.getFirst(); - skipCallbackParser |= pair.getSecond(); - - if (view != null) { - fillView(context, view, item, parentItem, callback, adapterRef); - } else { - // create a text view to display an error. - TextView tv = new TextView(context); - tv.setText("Unable to find layout: " + dataBindingItem.getViewReference().getName()); - view = tv; - } - - return Pair.of(view, skipCallbackParser); - } - - private static void fillView(BridgeContext context, View view, AdapterItem item, - AdapterItem parentItem, LayoutlibCallback callback, ResourceReference adapterRef) { - if (view instanceof ViewGroup) { - ViewGroup group = (ViewGroup) view; - final int count = group.getChildCount(); - for (int i = 0 ; i < count ; i++) { - fillView(context, group.getChildAt(i), item, parentItem, callback, adapterRef); - } - } else { - int id = view.getId(); - if (id != 0) { - ResourceReference resolvedRef = context.resolveId(id); - if (resolvedRef != null) { - int fullPosition = item.getFullPosition(); - int positionPerType = item.getPositionPerType(); - int fullParentPosition = parentItem != null ? parentItem.getFullPosition() : 0; - int parentPositionPerType = parentItem != null ? - parentItem.getPositionPerType() : 0; - - if (view instanceof TextView) { - TextView tv = (TextView) view; - Object value = callback.getAdapterItemValue( - adapterRef, context.getViewKey(view), - item.getDataBindingItem().getViewReference(), - fullPosition, positionPerType, - fullParentPosition, parentPositionPerType, - resolvedRef, ViewAttribute.TEXT, tv.getText().toString()); - if (value != null) { - if (value.getClass() != ViewAttribute.TEXT.getAttributeClass()) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, String.format( - "Wrong Adapter Item value class for TEXT. Expected String, got %s", - value.getClass().getName()), null); - } else { - tv.setText((String) value); - } - } - } - - if (view instanceof Checkable) { - Checkable cb = (Checkable) view; - - Object value = callback.getAdapterItemValue( - adapterRef, context.getViewKey(view), - item.getDataBindingItem().getViewReference(), - fullPosition, positionPerType, - fullParentPosition, parentPositionPerType, - resolvedRef, ViewAttribute.IS_CHECKED, cb.isChecked()); - if (value != null) { - if (value.getClass() != ViewAttribute.IS_CHECKED.getAttributeClass()) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, String.format( - "Wrong Adapter Item value class for IS_CHECKED. Expected Boolean, got %s", - value.getClass().getName()), null); - } else { - cb.setChecked((Boolean) value); - } - } - } - - if (view instanceof ImageView) { - ImageView iv = (ImageView) view; - - Object value = callback.getAdapterItemValue( - adapterRef, context.getViewKey(view), - item.getDataBindingItem().getViewReference(), - fullPosition, positionPerType, - fullParentPosition, parentPositionPerType, - resolvedRef, ViewAttribute.SRC, iv.getDrawable()); - if (value != null) { - if (value.getClass() != ViewAttribute.SRC.getAttributeClass()) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, String.format( - "Wrong Adapter Item value class for SRC. Expected Boolean, got %s", - value.getClass().getName()), null); - } else { - // FIXME - } - } - } - } - } - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterItem.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterItem.java deleted file mode 100644 index 8e28dbaf1a4d..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterItem.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 com.android.layoutlib.bridge.impl.binding; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import com.android.ide.common.rendering.api.DataBindingItem; - -/** - * This is the items provided by the adapter. They are dynamically generated. - */ -final class AdapterItem { - private final DataBindingItem mItem; - private final int mType; - private final int mFullPosition; - private final int mPositionPerType; - private List<AdapterItem> mChildren; - - protected AdapterItem(DataBindingItem item, int type, int fullPosition, - int positionPerType) { - mItem = item; - mType = type; - mFullPosition = fullPosition; - mPositionPerType = positionPerType; - } - - void addChild(AdapterItem child) { - if (mChildren == null) { - mChildren = new ArrayList<AdapterItem>(); - } - - mChildren.add(child); - } - - List<AdapterItem> getChildren() { - if (mChildren != null) { - return mChildren; - } - - return Collections.emptyList(); - } - - int getType() { - return mType; - } - - int getFullPosition() { - return mFullPosition; - } - - int getPositionPerType() { - return mPositionPerType; - } - - DataBindingItem getDataBindingItem() { - return mItem; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeAdapter.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeAdapter.java deleted file mode 100644 index 142eac172502..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeAdapter.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.impl.binding; - -import com.android.ide.common.rendering.api.AdapterBinding; -import com.android.ide.common.rendering.api.DataBindingItem; -import com.android.ide.common.rendering.api.LayoutlibCallback; -import com.android.ide.common.rendering.api.ResourceReference; -import com.android.util.Pair; - -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.BaseAdapter; -import android.widget.ListAdapter; -import android.widget.SpinnerAdapter; - -import java.util.ArrayList; -import java.util.List; - -/** - * Fake adapter to do fake data binding in {@link AdapterView} objects for {@link ListAdapter} - * and {@link SpinnerAdapter}. - * - */ -public class FakeAdapter extends BaseAdapter { - - // don't use a set because the order is important. - private final List<ResourceReference> mTypes = new ArrayList<ResourceReference>(); - private final LayoutlibCallback mCallback; - private final ResourceReference mAdapterRef; - private final List<AdapterItem> mItems = new ArrayList<AdapterItem>(); - private boolean mSkipCallbackParser = false; - - public FakeAdapter(ResourceReference adapterRef, AdapterBinding binding, - LayoutlibCallback callback) { - mAdapterRef = adapterRef; - mCallback = callback; - - final int repeatCount = binding.getRepeatCount(); - final int itemCount = binding.getItemCount(); - - // Need an array to count for each type. - // This is likely too big, but is the max it can be. - int[] typeCount = new int[itemCount]; - - // We put several repeating sets. - for (int r = 0 ; r < repeatCount ; r++) { - // loop on the type of list items, and add however many for each type. - for (DataBindingItem dataBindingItem : binding) { - ResourceReference viewRef = dataBindingItem.getViewReference(); - int typeIndex = mTypes.indexOf(viewRef); - if (typeIndex == -1) { - typeIndex = mTypes.size(); - mTypes.add(viewRef); - } - - int count = dataBindingItem.getCount(); - - int index = typeCount[typeIndex]; - typeCount[typeIndex] += count; - - for (int k = 0 ; k < count ; k++) { - mItems.add(new AdapterItem(dataBindingItem, typeIndex, mItems.size(), index++)); - } - } - } - } - - @Override - public boolean isEnabled(int position) { - return true; - } - - @Override - public int getCount() { - return mItems.size(); - } - - @Override - public Object getItem(int position) { - return mItems.get(position); - } - - @Override - public long getItemId(int position) { - return position; - } - - @Override - public int getItemViewType(int position) { - return mItems.get(position).getType(); - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - // we don't care about recycling here because we never scroll. - AdapterItem item = mItems.get(position); - @SuppressWarnings("deprecation") - Pair<View, Boolean> pair = AdapterHelper.getView(item, null, parent, mCallback, - mAdapterRef, mSkipCallbackParser); - mSkipCallbackParser = pair.getSecond(); - return pair.getFirst(); - } - - @Override - public int getViewTypeCount() { - return mTypes.size(); - } - - // ---- SpinnerAdapter - - @Override - public View getDropDownView(int position, View convertView, ViewGroup parent) { - // pass - return null; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeExpandableAdapter.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeExpandableAdapter.java deleted file mode 100644 index 344b17eab039..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeExpandableAdapter.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.impl.binding; - -import com.android.ide.common.rendering.api.AdapterBinding; -import com.android.ide.common.rendering.api.DataBindingItem; -import com.android.ide.common.rendering.api.LayoutlibCallback; -import com.android.ide.common.rendering.api.ResourceReference; -import com.android.util.Pair; - -import android.database.DataSetObserver; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ExpandableListAdapter; -import android.widget.HeterogeneousExpandableList; - -import java.util.ArrayList; -import java.util.List; - -@SuppressWarnings("deprecation") -public class FakeExpandableAdapter implements ExpandableListAdapter, HeterogeneousExpandableList { - - private final LayoutlibCallback mCallback; - private final ResourceReference mAdapterRef; - private boolean mSkipCallbackParser = false; - - protected final List<AdapterItem> mItems = new ArrayList<AdapterItem>(); - - // don't use a set because the order is important. - private final List<ResourceReference> mGroupTypes = new ArrayList<ResourceReference>(); - private final List<ResourceReference> mChildrenTypes = new ArrayList<ResourceReference>(); - - public FakeExpandableAdapter(ResourceReference adapterRef, AdapterBinding binding, - LayoutlibCallback callback) { - mAdapterRef = adapterRef; - mCallback = callback; - - createItems(binding, binding.getItemCount(), binding.getRepeatCount(), mGroupTypes, 1); - } - - private void createItems(Iterable<DataBindingItem> iterable, final int itemCount, - final int repeatCount, List<ResourceReference> types, int depth) { - // Need an array to count for each type. - // This is likely too big, but is the max it can be. - int[] typeCount = new int[itemCount]; - - // we put several repeating sets. - for (int r = 0 ; r < repeatCount ; r++) { - // loop on the type of list items, and add however many for each type. - for (DataBindingItem dataBindingItem : iterable) { - ResourceReference viewRef = dataBindingItem.getViewReference(); - int typeIndex = types.indexOf(viewRef); - if (typeIndex == -1) { - typeIndex = types.size(); - types.add(viewRef); - } - - List<DataBindingItem> children = dataBindingItem.getChildren(); - int count = dataBindingItem.getCount(); - - // if there are children, we use the count as a repeat count for the children. - if (children.size() > 0) { - count = 1; - } - - int index = typeCount[typeIndex]; - typeCount[typeIndex] += count; - - for (int k = 0 ; k < count ; k++) { - AdapterItem item = new AdapterItem(dataBindingItem, typeIndex, mItems.size(), - index++); - mItems.add(item); - - if (children.size() > 0) { - createItems(dataBindingItem, depth + 1); - } - } - } - } - } - - private void createItems(DataBindingItem item, int depth) { - if (depth == 2) { - createItems(item, item.getChildren().size(), item.getCount(), mChildrenTypes, depth); - } - } - - private AdapterItem getChildItem(int groupPosition, int childPosition) { - AdapterItem item = mItems.get(groupPosition); - - List<AdapterItem> children = item.getChildren(); - return children.get(childPosition); - } - - // ---- ExpandableListAdapter - - @Override - public int getGroupCount() { - return mItems.size(); - } - - @Override - public int getChildrenCount(int groupPosition) { - AdapterItem item = mItems.get(groupPosition); - return item.getChildren().size(); - } - - @Override - public Object getGroup(int groupPosition) { - return mItems.get(groupPosition); - } - - @Override - public Object getChild(int groupPosition, int childPosition) { - return getChildItem(groupPosition, childPosition); - } - - @Override - public View getGroupView(int groupPosition, boolean isExpanded, View convertView, - ViewGroup parent) { - // we don't care about recycling here because we never scroll. - AdapterItem item = mItems.get(groupPosition); - Pair<View, Boolean> pair = AdapterHelper.getView(item, null /*parentItem*/, parent, - mCallback, mAdapterRef, mSkipCallbackParser); - mSkipCallbackParser = pair.getSecond(); - return pair.getFirst(); - } - - @Override - public View getChildView(int groupPosition, int childPosition, boolean isLastChild, - View convertView, ViewGroup parent) { - // we don't care about recycling here because we never scroll. - AdapterItem parentItem = mItems.get(groupPosition); - AdapterItem item = getChildItem(groupPosition, childPosition); - Pair<View, Boolean> pair = AdapterHelper.getView(item, parentItem, parent, mCallback, - mAdapterRef, mSkipCallbackParser); - mSkipCallbackParser = pair.getSecond(); - return pair.getFirst(); - } - - @Override - public long getGroupId(int groupPosition) { - return groupPosition; - } - - @Override - public long getChildId(int groupPosition, int childPosition) { - return childPosition; - } - - @Override - public long getCombinedGroupId(long groupId) { - return groupId << 16 | 0x0000FFFF; - } - - @Override - public long getCombinedChildId(long groupId, long childId) { - return groupId << 16 | childId; - } - - @Override - public boolean isChildSelectable(int groupPosition, int childPosition) { - return true; - } - - @Override - public void onGroupCollapsed(int groupPosition) { - // pass - } - - @Override - public void onGroupExpanded(int groupPosition) { - // pass - } - - @Override - public void registerDataSetObserver(DataSetObserver observer) { - // pass - } - - @Override - public void unregisterDataSetObserver(DataSetObserver observer) { - // pass - } - - @Override - public boolean hasStableIds() { - return true; - } - - @Override - public boolean areAllItemsEnabled() { - return true; - } - - @Override - public boolean isEmpty() { - return mItems.isEmpty(); - } - - // ---- HeterogeneousExpandableList - - @Override - public int getChildType(int groupPosition, int childPosition) { - return getChildItem(groupPosition, childPosition).getType(); - } - - @Override - public int getChildTypeCount() { - return mChildrenTypes.size(); - } - - @Override - public int getGroupType(int groupPosition) { - return mItems.get(groupPosition).getType(); - } - - @Override - public int getGroupTypeCount() { - return mGroupTypes.size(); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/libcore/io/BridgeBufferIterator.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/libcore/io/BridgeBufferIterator.java deleted file mode 100644 index 96cba783d367..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/libcore/io/BridgeBufferIterator.java +++ /dev/null @@ -1,81 +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 com.android.layoutlib.bridge.libcore.io; - -import java.nio.ByteBuffer; - -import libcore.io.BufferIterator; - -/** - * Provides an implementation of {@link BufferIterator} over a {@link ByteBuffer}. - */ -public class BridgeBufferIterator extends BufferIterator { - - private final long mSize; - private final ByteBuffer mByteBuffer; - - public BridgeBufferIterator(long size, ByteBuffer buffer) { - mSize = size; - mByteBuffer = buffer; - } - - @Override - public void seek(int offset) { - assert offset <= mSize; - mByteBuffer.position(offset); - } - - @Override - public int pos() { - return mByteBuffer.position(); - } - - @Override - public void skip(int byteCount) { - int newPosition = mByteBuffer.position() + byteCount; - assert newPosition <= mSize; - mByteBuffer.position(newPosition); - } - - @Override - public void readByteArray(byte[] dst, int dstOffset, int byteCount) { - assert dst.length >= dstOffset + byteCount; - mByteBuffer.get(dst, dstOffset, byteCount); - } - - @Override - public byte readByte() { - return mByteBuffer.get(); - } - - @Override - public int readInt() { - return mByteBuffer.getInt(); - } - - @Override - public void readIntArray(int[] dst, int dstOffset, int intCount) { - while (--intCount >= 0) { - dst[dstOffset++] = mByteBuffer.getInt(); - } - } - - @Override - public short readShort() { - return mByteBuffer.getShort(); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/shadowutil/ShadowBuffer.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/shadowutil/ShadowBuffer.java deleted file mode 100644 index ae33e1ddf211..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/shadowutil/ShadowBuffer.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.shadowutil; - -import android.annotation.NonNull; -import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; -import android.graphics.Canvas; - -public class ShadowBuffer { - - private int mWidth; - private int mHeight; - private Bitmap mBitmap; - private int[] mData; - - public ShadowBuffer(int width, int height) { - mWidth = width; - mHeight = height; - mBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888); - mData = new int[mBitmap.getWidth() * mBitmap.getHeight()]; - mBitmap.getPixels(mData, 0, mBitmap.getWidth(), 0, 0, mBitmap.getWidth(), - mBitmap.getHeight()); - } - - public void generateTriangles(@NonNull float[] strip, float scale) { - for (int i = 0; i < strip.length - 8; i += 3) { - float fx3 = strip[i]; - float fy3 = strip[i + 1]; - float fz3 = scale * strip[i + 2]; - - float fx2 = strip[i + 3]; - float fy2 = strip[i + 4]; - float fz2 = scale * strip[i + 5]; - - float fx1 = strip[i + 6]; - float fy1 = strip[i + 7]; - float fz1 = scale * strip[i + 8]; - - if (fx1 * (fy2 - fy3) + fx2 * (fy3 - fy1) + fx3 * (fy1 - fy2) == 0) { - continue; - } - - triangleZBuffMin(mData, mWidth, mHeight, fx3, fy3, fz3, fx2, fy2, fz2, fx1, fy1, fz1); - triangleZBuffMin(mData, mWidth, mHeight, fx1, fy1, fz1, fx2, fy2, fz2, fx3, fy3, fz3); - } - mBitmap.setPixels(mData, 0, mBitmap.getWidth(), 0, 0, mBitmap.getWidth(), - mBitmap.getHeight()); - } - - private void triangleZBuffMin(@NonNull int[] buff, int w, int h, float fx3, float fy3, - float fz3, float fx2, float fy2, float fz2, float fx1, float fy1, float fz1) { - if (((fx1 - fx2) * (fy3 - fy2) - (fy1 - fy2) * (fx3 - fx2)) < 0) { - float tmpX = fx1; - float tmpY = fy1; - float tmpZ = fz1; - fx1 = fx2; - fy1 = fy2; - fz1 = fz2; - fx2 = tmpX; - fy2 = tmpY; - fz2 = tmpZ; - } - double d = (fx1 * (fy3 - fy2) - fx2 * fy3 + fx3 * fy2 + (fx2 - fx3) * fy1); - - if (d == 0) { - return; - } - float dx = (float) (-(fy1 * (fz3 - fz2) - fy2 * fz3 + fy3 * fz2 + (fy2 - fy3) * fz1) / d); - float dy = (float) ((fx1 * (fz3 - fz2) - fx2 * fz3 + fx3 * fz2 + (fx2 - fx3) * fz1) / d); - float zOff = (float) ((fx1 * (fy3 * fz2 - fy2 * fz3) + fy1 * (fx2 * fz3 - fx3 * fz2) + - (fx3 * fy2 - fx2 * fy3) * fz1) / d); - - int Y1 = (int) (16.0f * fy1 + .5f); - int Y2 = (int) (16.0f * fy2 + .5f); - int Y3 = (int) (16.0f * fy3 + .5f); - - int X1 = (int) (16.0f * fx1 + .5f); - int X2 = (int) (16.0f * fx2 + .5f); - int X3 = (int) (16.0f * fx3 + .5f); - - int DX12 = X1 - X2; - int DX23 = X2 - X3; - int DX31 = X3 - X1; - - int DY12 = Y1 - Y2; - int DY23 = Y2 - Y3; - int DY31 = Y3 - Y1; - - int FDX12 = DX12 << 4; - int FDX23 = DX23 << 4; - int FDX31 = DX31 << 4; - - int FDY12 = DY12 << 4; - int FDY23 = DY23 << 4; - int FDY31 = DY31 << 4; - - int minX = (min(X1, X2, X3) + 0xF) >> 4; - int maxX = (max(X1, X2, X3) + 0xF) >> 4; - int minY = (min(Y1, Y2, Y3) + 0xF) >> 4; - int maxY = (max(Y1, Y2, Y3) + 0xF) >> 4; - - if (minY < 0) { - minY = 0; - } - if (minX < 0) { - minX = 0; - } - if (maxX > w) { - maxX = w; - } - if (maxY > h) { - maxY = h; - } - int off = minY * w; - - int C1 = DY12 * X1 - DX12 * Y1; - int C2 = DY23 * X2 - DX23 * Y2; - int C3 = DY31 * X3 - DX31 * Y3; - - if (DY12 < 0 || (DY12 == 0 && DX12 > 0)) { - C1++; - } - if (DY23 < 0 || (DY23 == 0 && DX23 > 0)) { - C2++; - } - if (DY31 < 0 || (DY31 == 0 && DX31 > 0)) { - C3++; - } - int CY1 = C1 + DX12 * (minY << 4) - DY12 * (minX << 4); - int CY2 = C2 + DX23 * (minY << 4) - DY23 * (minX << 4); - int CY3 = C3 + DX31 * (minY << 4) - DY31 * (minX << 4); - - for (int y = minY; y < maxY; y++) { - int CX1 = CY1; - int CX2 = CY2; - int CX3 = CY3; - float p = zOff + dy * y; - for (int x = minX; x < maxX; x++) { - if (CX1 > 0 && CX2 > 0 && CX3 > 0) { - int point = x + off; - float zVal = p + dx * x; - buff[point] |= ((int) (zVal * 255)) << 24; - } - CX1 -= FDY12; - CX2 -= FDY23; - CX3 -= FDY31; - } - CY1 += FDX12; - CY2 += FDX23; - CY3 += FDX31; - off += w; - } - } - - private int min(int x1, int x2, int x3) { - return (x1 > x2) ? ((x2 > x3) ? x3 : x2) : ((x1 > x3) ? x3 : x1); - } - - private int max(int x1, int x2, int x3) { - return (x1 < x2) ? ((x2 < x3) ? x3 : x2) : ((x1 < x3) ? x3 : x1); - } - - public void draw(@NonNull Canvas c) { - c.drawBitmap(mBitmap, 0, 0, null); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/shadowutil/SpotShadow.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/shadowutil/SpotShadow.java deleted file mode 100644 index 33375ffb7487..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/shadowutil/SpotShadow.java +++ /dev/null @@ -1,630 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.shadowutil; - -import android.annotation.NonNull; - -public class SpotShadow { - - private static float rayIntersectPoly(@NonNull float[] poly, int polyLength, float px, float py, - float dx, float dy) { - int p1 = polyLength - 1; - for (int p2 = 0; p2 < polyLength; p2++) { - float p1x = poly[p1 * 2 + 0]; - float p1y = poly[p1 * 2 + 1]; - float p2x = poly[p2 * 2 + 0]; - float p2y = poly[p2 * 2 + 1]; - float div = (dx * (p1y - p2y) + dy * p2x - dy * p1x); - if (div != 0) { - float t = (dx * (p1y - py) + dy * px - dy * p1x) / (div); - if (t >= 0 && t <= 1) { - float t2 = (p1x * (py - p2y) + p2x * (p1y - py) + px * (p2y - p1y)) / div; - if (t2 > 0) { - return t2; - } - } - } - p1 = p2; - } - return Float.NaN; - } - - private static void centroid2d(@NonNull float[] poly, int len, @NonNull float[] ret) { - float sumX = 0; - float sumY = 0; - int p1 = len - 1; - float area = 0; - for (int p2 = 0; p2 < len; p2++) { - float x1 = poly[p1 * 2 + 0]; - float y1 = poly[p1 * 2 + 1]; - float x2 = poly[p2 * 2 + 0]; - float y2 = poly[p2 * 2 + 1]; - float a = (x1 * y2 - x2 * y1); - sumX += (x1 + x2) * a; - sumY += (y1 + y2) * a; - area += a; - p1 = p2; - } - - float centroidX = sumX / (3 * area); - float centroidY = sumY / (3 * area); - ret[0] = centroidX; - ret[1] = centroidY; - } - - /** - * calculates the Centroid of a 3d polygon - * @param poly The flatten 3d vertices coordinates of polygon, the format is like - * [x0, y0, z0, x1, y1, z1, x2, ...] - * @param len The number of polygon vertices. So the length of poly should be len * 3. - * @param ret The array used to sotre the result. The length should be 3. - */ - private static void centroid3d(@NonNull float[] poly, int len, @NonNull float[] ret) { - int n = len - 1; - double area = 0; - double cx = 0, cy = 0, cz = 0; - for (int i = 1; i < n; i++) { - int k = i + 1; - float a0 = poly[i * 3 + 0] - poly[0 * 3 + 0]; - float a1 = poly[i * 3 + 1] - poly[0 * 3 + 1]; - float a2 = poly[i * 3 + 2] - poly[0 * 3 + 2]; - float b0 = poly[k * 3 + 0] - poly[0 * 3 + 0]; - float b1 = poly[k * 3 + 1] - poly[0 * 3 + 1]; - float b2 = poly[k * 3 + 2] - poly[0 * 3 + 2]; - float c0 = a1 * b2 - b1 * a2; - float c1 = a2 * b0 - b2 * a0; - float c2 = a0 * b1 - b0 * a1; - double areaOfTriangle = Math.sqrt(c0 * c0 + c1 * c1 + c2 * c2); - area += areaOfTriangle; - cx += areaOfTriangle * (poly[i * 3 + 0] + poly[k * 3 + 0] + poly[0 * 3 + 0]); - cy += areaOfTriangle * (poly[i * 3 + 1] + poly[k * 3 + 1] + poly[0 * 3 + 1]); - cz += areaOfTriangle * (poly[i * 3 + 2] + poly[k * 3 + 2] + poly[0 * 3 + 2]); - } - ret[0] = (float) (cx / (3 * area)); - ret[1] = (float) (cy / (3 * area)); - ret[2] = (float) (cz / (3 * area)); - } - - /** - * Extracts the convex hull of a polygon. - * @param points The vertices coordinates of polygon - * @param pointsLength The number of polygon vertices. So the length of poly should be len * 3. - * @param retPoly retPoly is at most the size of the input polygon - * @return The number of points in the retPolygon - */ - private static int hull(@NonNull float[] points, int pointsLength, @NonNull float[] retPoly) { - quicksortX(points, 0, pointsLength - 1); - int n = pointsLength; - float[] lUpper = new float[n * 2]; - lUpper[0] = points[0]; - lUpper[1] = points[1]; - lUpper[2] = points[2]; - lUpper[3] = points[3]; - - int lUpperSize = 2; - - for (int i = 2; i < n; i++) { - lUpper[lUpperSize * 2 + 0] = points[i * 2 + 0]; - lUpper[lUpperSize * 2 + 1] = points[i * 2 + 1]; - lUpperSize++; - - while (lUpperSize > 2 && - !rightTurn(lUpper[(lUpperSize - 3) * 2], lUpper[(lUpperSize - 3) * 2 + 1], - lUpper[(lUpperSize - 2) * 2], lUpper[(lUpperSize - 2) * 2 + 1], - lUpper[(lUpperSize - 1) * 2], lUpper[(lUpperSize - 1) * 2 + 1])) { - // Remove the middle point of the three last - lUpper[(lUpperSize - 2) * 2 + 0] = lUpper[(lUpperSize - 1) * 2 + 0]; - lUpper[(lUpperSize - 2) * 2 + 1] = lUpper[(lUpperSize - 1) * 2 + 1]; - lUpperSize--; - } - } - - float[] lLower = new float[n * 2]; - lLower[0] = points[(n - 1) * 2 + 0]; - lLower[1] = points[(n - 1) * 2 + 1]; - lLower[2] = points[(n - 2) * 2 + 0]; - lLower[3] = points[(n - 2) * 2 + 1]; - - int lLowerSize = 2; - - for (int i = n - 3; i >= 0; i--) { - lLower[lLowerSize * 2 + 0] = points[i * 2 + 0]; - lLower[lLowerSize * 2 + 1] = points[i * 2 + 1]; - lLowerSize++; - - while (lLowerSize > 2 && - !rightTurn(lLower[(lLowerSize - 3) * 2], lLower[(lLowerSize - 3) * 2 + 1], - lLower[(lLowerSize - 2) * 2], lLower[(lLowerSize - 2) * 2 + 1], - lLower[(lLowerSize - 1) * 2], lLower[(lLowerSize - 1) * 2 + 1])) { - // Remove the middle point of the three last - lLower[(lLowerSize - 2) * 2 + 0] = lLower[(lLowerSize - 1) * 2 + 0]; - lLower[(lLowerSize - 2) * 2 + 1] = lLower[(lLowerSize - 1) * 2 + 1]; - lLowerSize--; - } - } - - int count = 0; - for (int i = 0; i < lUpperSize; i++) { - retPoly[count * 2 + 0] = lUpper[i * 2 + 0]; - retPoly[count * 2 + 1] = lUpper[i * 2 + 1]; - count++; - } - for (int i = 1; i < lLowerSize - 1; i++) { - retPoly[count * 2 + 0] = lLower[i * 2 + 0]; - retPoly[count * 2 + 1] = lLower[i * 2 + 1]; - count++; - } - return count; - } - - private static boolean rightTurn(float ax, float ay, float bx, float by, float cx, float cy) { - return (bx - ax) * (cy - ay) - (by - ay) * (cx - ax) > 0.00001; - } - - /** - * calculates the intersection of poly1 with poly2 and put in poly2 - * @param poly1 The flatten 2d coordinates of polygon - * @param poly1length The vertices number of poly1 - * @param poly2 The flatten 2d coordinates of polygon - * @param poly2length The vertices number of poly2 - * @return number of vertices in poly2 - */ - private static int intersection(@NonNull float[] poly1, int poly1length, @NonNull float[] poly2, - int poly2length) { - makeClockwise(poly1, poly1length); - makeClockwise(poly2, poly2length); - float[] poly = new float[(poly1length * poly2length + 2) * 2]; - int count = 0; - int pCount = 0; - for (int i = 0; i < poly1length; i++) { - if (pointInsidePolygon(poly1[i * 2 + 0], poly1[i * 2 + 1], poly2, poly2length)) { - poly[count * 2 + 0] = poly1[i * 2 + 0]; - poly[count * 2 + 1] = poly1[i * 2 + 1]; - count++; - pCount++; - } - } - int fromP1 = pCount; - for (int i = 0; i < poly2length; i++) { - if (pointInsidePolygon(poly2[i * 2 + 0], poly2[i * 2 + 1], poly1, poly1length)) { - poly[count * 2 + 0] = poly2[i * 2 + 0]; - poly[count * 2 + 1] = poly2[i * 2 + 1]; - count++; - } - } - int fromP2 = count - fromP1; - if (fromP1 == poly1length) { // use p1 - for (int i = 0; i < poly1length; i++) { - poly2[i * 2 + 0] = poly1[i * 2 + 0]; - poly2[i * 2 + 1] = poly1[i * 2 + 1]; - } - return poly1length; - } - if (fromP2 == poly2length) { // use p2 - return poly2length; - } - float[] intersection = new float[2]; - for (int i = 0; i < poly2length; i++) { - for (int j = 0; j < poly1length; j++) { - int i1_by_2 = i * 2; - int i2_by_2 = ((i + 1) % poly2length) * 2; - int j1_by_2 = j * 2; - int j2_by_2 = ((j + 1) % poly1length) * 2; - boolean found = - lineIntersection(poly2[i1_by_2 + 0], poly2[i1_by_2 + 1], poly2[i2_by_2 + 0], - poly2[i2_by_2 + 1], poly1[j1_by_2 + 0], poly1[j1_by_2 + 1], - poly1[j2_by_2 + 0], poly1[j2_by_2 + 1], intersection); - if (found) { - poly[count * 2 + 0] = intersection[0]; - poly[count * 2 + 1] = intersection[1]; - count++; - } else { - float dx = poly2[i * 2 + 0] - poly1[j * 2 + 0]; - float dy = poly2[i * 2 + 1] - poly1[j * 2 + 1]; - - if (dx * dx + dy * dy < 0.01) { - poly[count * 2 + 0] = poly2[i * 2 + 0]; - poly[count * 2 + 1] = poly2[i * 2 + 1]; - count++; - } - } - } - } - if (count == 0) { - return 0; - } - float avgX = 0; - float avgY = 0; - for (int i = 0; i < count; i++) { - avgX += poly[i * 2 + 0]; - avgY += poly[i * 2 + 1]; - } - avgX /= count; - avgY /= count; - - float[] ctr = new float[]{avgX, avgY}; - sort(poly, count, ctr); - int size = count; - - poly2[0] = poly[0]; - poly2[1] = poly[1]; - - count = 1; - for (int i = 1; i < size; i++) { - float dx = poly[i * 2 + 0] - poly[(i - 1) * 2 + 0]; - float dy = poly[i * 2 + 1] - poly[(i - 1) * 2 + 1]; - if (dx * dx + dy * dy >= 0.01) { - poly2[count * 2 + 0] = poly[i * 2 + 0]; - poly2[count * 2 + 1] = poly[i * 2 + 1]; - count++; - } - } - return count; - } - - public static void sort(@NonNull float[] poly, int polyLength, @NonNull float[] ctr) { - quicksortCircle(poly, 0, polyLength - 1, ctr); - } - - public static float angle(float x1, float y1, @NonNull float[] ctr) { - return -(float) Math.atan2(x1 - ctr[0], y1 - ctr[1]); - } - - private static void swapPair(@NonNull float[] points, int i, int j) { - float x = points[i * 2 + 0]; - float y = points[i * 2 + 1]; - points[i * 2 + 0] = points[j * 2 + 0]; - points[i * 2 + 1] = points[j * 2 + 1]; - points[j * 2 + 0] = x; - points[j * 2 + 1] = y; - } - - private static void quicksortCircle(@NonNull float[] points, int low, int high, - @NonNull float[] ctr) { - int i = low, j = high; - int p = low + (high - low) / 2; - float pivot = angle(points[p * 2], points[p * 2 + 1], ctr); - while (i <= j) { - while (angle(points[i * 2 + 0], points[i * 2 + 1], ctr) < pivot) { - i++; - } - while (angle(points[j * 2 + 0], points[j * 2 + 1], ctr) > pivot) { - j--; - } - if (i <= j) { - swapPair(points, i, j); - i++; - j--; - } - } - if (low < j) { - quicksortCircle(points, low, j, ctr); - } - if (i < high) { - quicksortCircle(points, i, high, ctr); - } - } - - /** - * This function do Quick Sort by comparing X axis only.<br> - * Note that the input values of points are paired coordinates, e.g. {@code [x0, y0, x1, y1, x2, - * y2, ...]).} - * @param points The input point pairs. Every {@code (2 * i, 2 * i + 1)} points are pairs. - * @param low lowest index used to do quick sort sort - * @param high highest index used to do quick sort - */ - private static void quicksortX(@NonNull float[] points, int low, int high) { - int i = low, j = high; - int p = low + (high - low) / 2; - float pivot = points[p * 2]; - while (i <= j) { - while (points[i * 2 + 0] < pivot) { - i++; - } - while (points[j * 2 + 0] > pivot) { - j--; - } - - if (i <= j) { - swapPair(points, i, j); - i++; - j--; - } - } - if (low < j) { - quicksortX(points, low, j); - } - if (i < high) { - quicksortX(points, i, high); - } - } - - private static boolean pointInsidePolygon(float x, float y, @NonNull float[] poly, int len) { - boolean c = false; - float testX = x; - float testY = y; - for (int i = 0, j = len - 1; i < len; j = i++) { - if (((poly[i * 2 + 1] > testY) != (poly[j * 2 + 1] > testY)) && (testX < - (poly[j * 2 + 0] - poly[i * 2 + 0]) * (testY - poly[i * 2 + 1]) / - (poly[j * 2 + 1] - poly[i * 2 + 1]) + poly[i * 2 + 0])) { - c = !c; - } - } - return c; - } - - private static void makeClockwise(@NonNull float[] polygon, int len) { - if (polygon == null || len == 0) { - return; - } - if (!isClockwise(polygon, len)) { - reverse(polygon, len); - } - } - - private static boolean isClockwise(@NonNull float[] polygon, int len) { - float sum = 0; - float p1x = polygon[(len - 1) * 2 + 0]; - float p1y = polygon[(len - 1) * 2 + 1]; - for (int i = 0; i < len; i++) { - float p2x = polygon[i * 2 + 0]; - float p2y = polygon[i * 2 + 1]; - sum += p1x * p2y - p2x * p1y; - p1x = p2x; - p1y = p2y; - } - return sum < 0; - } - - private static void reverse(@NonNull float[] polygon, int len) { - int n = len / 2; - for (int i = 0; i < n; i++) { - float tmp0 = polygon[i * 2 + 0]; - float tmp1 = polygon[i * 2 + 1]; - int k = len - 1 - i; - polygon[i * 2 + 0] = polygon[k * 2 + 0]; - polygon[i * 2 + 1] = polygon[k * 2 + 1]; - polygon[k * 2 + 0] = tmp0; - polygon[k * 2 + 1] = tmp1; - } - } - - /** - * Intersects two lines in parametric form. - */ - private static final boolean lineIntersection(float x1, float y1, float x2, float y2, float x3, - float y3, float x4, float y4, @NonNull float[] ret) { - float d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4); - if (d == 0.000f) { - return false; - } - - float dx = (x1 * y2 - y1 * x2); - float dy = (x3 * y4 - y3 * x4); - float x = (dx * (x3 - x4) - (x1 - x2) * dy) / d; - float y = (dx * (y3 - y4) - (y1 - y2) * dy) / d; - - if (((x - x1) * (x - x2) > 0.0000001) || ((x - x3) * (x - x4) > 0.0000001) || - ((y - y1) * (y - y2) > 0.0000001) || ((y - y3) * (y - y4) > 0.0000001)) { - return false; - } - ret[0] = x; - ret[1] = y; - return true; - } - - @NonNull - public static float[] calculateLight(float size, int points, float x, float y, float height) { - float[] ret = new float[points * 3]; - for (int i = 0; i < points; i++) { - double angle = 2 * i * Math.PI / points; - ret[i * 3 + 0] = (float) Math.cos(angle) * size + x; - ret[i * 3 + 1] = (float) Math.sin(angle) * size + y; - ret[i * 3 + 2] = (height); - } - return ret; - } - - /** - layers indicates the number of circular strips to generate. - Strength is how dark a shadow to generate. - - /** - * This calculates a collection of triangles that represent the shadow cast by a polygonal - * light source (lightPoly) hitting a convex polygon (poly). - * @param lightPoly The flatten 3d coordinates of light - * @param lightPolyLength The vertices number of light polygon. - * @param poly The flatten 3d coordinates of item - * @param polyLength The vertices number of light polygon. - * @param rays defines the number of points around the perimeter of the shadow to generate - * @param layers The number of shadow's fading. - * @param strength The factor of the black color of shadow. - * @param retStrips Used to store the calculated shadow strength - * @return true if the params is able to calculate a shadow, else false. - */ - public static boolean calcShadow(@NonNull float[] lightPoly, int lightPolyLength, - @NonNull float[] poly, int polyLength, int rays, int layers, float strength, - @NonNull float[] retStrips) { - float[] shadowRegion = new float[lightPolyLength * polyLength * 2]; - float[] outline = new float[polyLength * 2]; - float[] umbra = new float[polyLength * lightPolyLength * 2]; - int umbraLength = 0; - - int k = 0; - for (int j = 0; j < lightPolyLength; j++) { - int m = 0; - for (int i = 0; i < polyLength; i++) { - float t = lightPoly[j * 3 + 2] - poly[i * 3 + 2]; - if (t == 0) { - return false; - } - t = lightPoly[j * 3 + 2] / t; - float x = lightPoly[j * 3 + 0] - t * (lightPoly[j * 3 + 0] - poly[i * 3 + 0]); - float y = lightPoly[j * 3 + 1] - t * (lightPoly[j * 3 + 1] - poly[i * 3 + 1]); - - shadowRegion[k * 2 + 0] = x; - shadowRegion[k * 2 + 1] = y; - outline[m * 2 + 0] = x; - outline[m * 2 + 1] = y; - - k++; - m++; - } - if (umbraLength == 0) { - System.arraycopy(outline, 0, umbra, 0, polyLength); - umbraLength = polyLength; - } else { - umbraLength = intersection(outline, polyLength, umbra, umbraLength); - if (umbraLength == 0) { - break; - } - } - } - int shadowRegionLength = k; - - float[] penumbra = new float[k * 2]; - int penumbraLength = hull(shadowRegion, shadowRegionLength, penumbra); - if (umbraLength < 3) {// no real umbra make a fake one - float[] p = new float[3]; - centroid3d(lightPoly, lightPolyLength, p); - float[] centShadow = new float[polyLength * 2]; - for (int i = 0; i < polyLength; i++) { - float t = p[2] - poly[i * 3 + 2]; - if (t == 0) { - return false; - } - t = p[2] / t; - float x = p[0] - t * (p[0] - poly[i * 3 + 0]); - float y = p[1] - t * (p[1] - poly[i * 3 + 1]); - - centShadow[i * 2 + 0] = x; - centShadow[i * 2 + 1] = y; - } - float[] c = new float[2]; - centroid2d(centShadow, polyLength, c); - for (int i = 0; i < polyLength; i++) { - centShadow[i * 2 + 0] = (c[0] * 9 + centShadow[i * 2 + 0]) / 10; - centShadow[i * 2 + 1] = (c[1] * 9 + centShadow[i * 2 + 1]) / 10; - } - umbra = centShadow; // fake umbra - umbraLength = polyLength; // same size as the original polygon - } - - triangulateConcentricPolygon(penumbra, penumbraLength, umbra, umbraLength, rays, layers, - strength, retStrips); - return true; - } - - /** - * triangulate concentric circles. - * This takes the inner and outer polygons of the umbra and penumbra and triangulates it. - * @param penumbra The 2d flatten vertices of penumbra polygons. - * @param penumbraLength The number of vertices in penumbra. - * @param umbra The 2d flatten vertices of umbra polygons. - * @param umbraLength The number of vertices in umbra. - * @param rays defines the number of points around the perimeter of the shadow to generate - * @param layers The number of shadow's fading. - * @param strength The factor of the black color of shadow. - * @param retStrips Used to store the calculated shadow strength. - */ - private static void triangulateConcentricPolygon(@NonNull float[] penumbra, int penumbraLength, - @NonNull float[] umbra, int umbraLength, int rays, int layers, float strength, - @NonNull float[] retStrips) { - int rings = layers + 1; - double step = Math.PI * 2 / rays; - float[] retXY = new float[2]; - centroid2d(umbra, umbraLength, retXY); - float cx = retXY[0]; - float cy = retXY[1]; - - float[] t1 = new float[rays]; - float[] t2 = new float[rays]; - - for (int i = 0; i < rays; i++) { - float dx = (float) Math.cos(Math.PI / 4 + step * i); - float dy = (float) Math.sin(Math.PI / 4 + step * i); - t2[i] = rayIntersectPoly(umbra, umbraLength, cx, cy, dx, dy); - t1[i] = rayIntersectPoly(penumbra, penumbraLength, cx, cy, dx, dy); - } - - int p = 0; - // Calculate the vertex - for (int r = 0; r < layers; r++) { - int startP = p; - for (int i = 0; i < rays; i++) { - float dx = (float) Math.cos(Math.PI / 4 + step * i); - float dy = (float) Math.sin(Math.PI / 4 + step * i); - - for (int j = r; j < (r + 2); j++) { - float jf = j / (float) (rings - 1); - float t = t1[i] + jf * (t2[i] - t1[i]); - float op = (jf + 1 - 1 / (1 + (t - t1[i]) * (t - t1[i]))) / 2; - retStrips[p * 3 + 0] = dx * t + cx; - retStrips[p * 3 + 1] = dy * t + cy; - retStrips[p * 3 + 2] = jf * op * strength; - p++; - - } - } - retStrips[p * 3 + 0] = retStrips[startP * 3 + 0]; - retStrips[p * 3 + 1] = retStrips[startP * 3 + 1]; - retStrips[p * 3 + 2] = retStrips[startP * 3 + 2]; - p++; - startP++; - retStrips[p * 3 + 0] = retStrips[startP * 3 + 0]; - retStrips[p * 3 + 1] = retStrips[startP * 3 + 1]; - retStrips[p * 3 + 2] = retStrips[startP * 3 + 2]; - p++; - } - int oldP = p - 1; - retStrips[p * 3 + 0] = retStrips[oldP * 3 + 0]; - retStrips[p * 3 + 1] = retStrips[oldP * 3 + 1]; - retStrips[p * 3 + 2] = retStrips[oldP * 3 + 2]; - p++; - - // Skip the first point here, then make it same as last point later. - oldP = p; - p++; - for (int k = 0; k < rays; k++) { - int i = k / 2; - if ((k & 1) == 1) { // traverse the inside in a zig zag pattern - // for strips - i = rays - i - 1; - } - float dx = (float) Math.cos(Math.PI / 4 + step * i); - float dy = (float) Math.sin(Math.PI / 4 + step * i); - - float jf = 1; - - float t = t1[i] + jf * (t2[i] - t1[i]); - float op = (jf + 1 - 1 / (1 + (t - t1[i]) * (t - t1[i]))) / 2; - - retStrips[p * 3 + 0] = dx * t + cx; - retStrips[p * 3 + 1] = dy * t + cy; - retStrips[p * 3 + 2] = jf * op * strength; - p++; - } - p = oldP; - retStrips[p * 3 + 0] = retStrips[oldP * 3 + 0]; - retStrips[p * 3 + 1] = retStrips[oldP * 3 + 1]; - retStrips[p * 3 + 2] = retStrips[oldP * 3 + 2]; - } - - public static int getStripSize(int rays, int layers) { - return (2 + rays + ((layers) * 2 * (rays + 1))); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/CachedPathIteratorFactory.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/CachedPathIteratorFactory.java deleted file mode 100644 index 0a9b9ecde2f8..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/CachedPathIteratorFactory.java +++ /dev/null @@ -1,485 +0,0 @@ -/* - * 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 com.android.layoutlib.bridge.util; - -import android.annotation.NonNull; - -import java.awt.geom.CubicCurve2D; -import java.awt.geom.PathIterator; -import java.awt.geom.Point2D; -import java.awt.geom.QuadCurve2D; -import java.util.ArrayList; - -import com.google.android.collect.Lists; - -/** - * Class that returns iterators for a given path. These iterators are lightweight and can be reused - * multiple times to iterate over the path. - */ -public class CachedPathIteratorFactory { - /* - * A few conventions used in the code: - * Coordinates or coords arrays store segment coordinates. They use the same format as - * PathIterator#currentSegment coordinates array. - * float arrays store always points where the first element is X and the second is Y. - */ - - // This governs how accurate the approximation of the Path is. - private static final float PRECISION = 0.002f; - - private final int mWindingRule; - private final int[] mTypes; - private final float[][] mCoordinates; - private final float[] mSegmentsLength; - private final float mTotalLength; - - public CachedPathIteratorFactory(@NonNull PathIterator iterator) { - mWindingRule = iterator.getWindingRule(); - - ArrayList<Integer> typesArray = Lists.newArrayList(); - ArrayList<float[]> pointsArray = Lists.newArrayList(); - float[] points = new float[6]; - while (!iterator.isDone()) { - int type = iterator.currentSegment(points); - int nPoints = getNumberOfPoints(type) * 2; // 2 coordinates per point - - typesArray.add(type); - float[] itemPoints = new float[nPoints]; - System.arraycopy(points, 0, itemPoints, 0, nPoints); - pointsArray.add(itemPoints); - iterator.next(); - } - - mTypes = new int[typesArray.size()]; - mCoordinates = new float[mTypes.length][]; - for (int i = 0; i < typesArray.size(); i++) { - mTypes[i] = typesArray.get(i); - mCoordinates[i] = pointsArray.get(i); - } - - // Do measurement - mSegmentsLength = new float[mTypes.length]; - - // Curves that we can reuse to estimate segments length - CubicCurve2D.Float cubicCurve = new CubicCurve2D.Float(); - QuadCurve2D.Float quadCurve = new QuadCurve2D.Float(); - float lastX = 0; - float lastY = 0; - float totalLength = 0; - for (int i = 0; i < mTypes.length; i++) { - switch (mTypes[i]) { - case PathIterator.SEG_CUBICTO: - cubicCurve.setCurve(lastX, lastY, - mCoordinates[i][0], mCoordinates[i][1], mCoordinates[i][2], - mCoordinates[i][3], lastX = mCoordinates[i][4], - lastY = mCoordinates[i][5]); - mSegmentsLength[i] = - getFlatPathLength(cubicCurve.getPathIterator(null, PRECISION)); - break; - case PathIterator.SEG_QUADTO: - quadCurve.setCurve(lastX, lastY, mCoordinates[i][0], mCoordinates[i][1], - lastX = mCoordinates[i][2], lastY = mCoordinates[i][3]); - mSegmentsLength[i] = - getFlatPathLength(quadCurve.getPathIterator(null, PRECISION)); - break; - case PathIterator.SEG_CLOSE: - mSegmentsLength[i] = (float) Point2D.distance(lastX, lastY, - lastX = mCoordinates[0][0], - lastY = mCoordinates[0][1]); - mCoordinates[i] = new float[2]; - // We convert a SEG_CLOSE segment to a SEG_LINETO so we do not have to worry - // about this special case in the rest of the code. - mTypes[i] = PathIterator.SEG_LINETO; - mCoordinates[i][0] = mCoordinates[0][0]; - mCoordinates[i][1] = mCoordinates[0][1]; - break; - case PathIterator.SEG_MOVETO: - mSegmentsLength[i] = 0; - lastX = mCoordinates[i][0]; - lastY = mCoordinates[i][1]; - break; - case PathIterator.SEG_LINETO: - mSegmentsLength[i] = (float) Point2D.distance(lastX, lastY, mCoordinates[i][0], - mCoordinates[i][1]); - lastX = mCoordinates[i][0]; - lastY = mCoordinates[i][1]; - default: - } - totalLength += mSegmentsLength[i]; - } - - mTotalLength = totalLength; - } - - private static void quadCurveSegment(float[] coords, float t0, float t1) { - // Calculate X and Y at 0.5 (We'll use this to reconstruct the control point later) - float mt = t0 + (t1 - t0) / 2; - float mu = 1 - mt; - float mx = mu * mu * coords[0] + 2 * mu * mt * coords[2] + mt * mt * coords[4]; - float my = mu * mu * coords[1] + 2 * mu * mt * coords[3] + mt * mt * coords[5]; - - float u0 = 1 - t0; - float u1 = 1 - t1; - - // coords at t0 - coords[0] = coords[0] * u0 * u0 + coords[2] * 2 * t0 * u0 + coords[4] * t0 * t0; - coords[1] = coords[1] * u0 * u0 + coords[3] * 2 * t0 * u0 + coords[5] * t0 * t0; - - // coords at t1 - coords[4] = coords[0] * u1 * u1 + coords[2] * 2 * t1 * u1 + coords[4] * t1 * t1; - coords[5] = coords[1] * u1 * u1 + coords[3] * 2 * t1 * u1 + coords[5] * t1 * t1; - - // estimated control point at t'=0.5 - coords[2] = 2 * mx - coords[0] / 2 - coords[4] / 2; - coords[3] = 2 * my - coords[1] / 2 - coords[5] / 2; - } - - private static void cubicCurveSegment(float[] coords, float t0, float t1) { - // http://stackoverflow.com/questions/11703283/cubic-bezier-curve-segment - float u0 = 1 - t0; - float u1 = 1 - t1; - - // Calculate the points at t0 and t1 for the quadratic curves formed by (P0, P1, P2) and - // (P1, P2, P3) - float qxa = coords[0] * u0 * u0 + coords[2] * 2 * t0 * u0 + coords[4] * t0 * t0; - float qxb = coords[0] * u1 * u1 + coords[2] * 2 * t1 * u1 + coords[4] * t1 * t1; - float qxc = coords[2] * u0 * u0 + coords[4] * 2 * t0 * u0 + coords[6] * t0 * t0; - float qxd = coords[2] * u1 * u1 + coords[4] * 2 * t1 * u1 + coords[6] * t1 * t1; - - float qya = coords[1] * u0 * u0 + coords[3] * 2 * t0 * u0 + coords[5] * t0 * t0; - float qyb = coords[1] * u1 * u1 + coords[3] * 2 * t1 * u1 + coords[5] * t1 * t1; - float qyc = coords[3] * u0 * u0 + coords[5] * 2 * t0 * u0 + coords[7] * t0 * t0; - float qyd = coords[3] * u1 * u1 + coords[5] * 2 * t1 * u1 + coords[7] * t1 * t1; - - // Linear interpolation - coords[0] = qxa * u0 + qxc * t0; - coords[1] = qya * u0 + qyc * t0; - - coords[2] = qxa * u1 + qxc * t1; - coords[3] = qya * u1 + qyc * t1; - - coords[4] = qxb * u0 + qxd * t0; - coords[5] = qyb * u0 + qyd * t0; - - coords[6] = qxb * u1 + qxd * t1; - coords[7] = qyb * u1 + qyd * t1; - } - - /** - * Returns the end point of a given segment - * - * @param type the segment type - * @param coords the segment coordinates array - * @param point the return array where the point will be stored - */ - private static void getShapeEndPoint(int type, @NonNull float[] coords, @NonNull float[] - point) { - // start index of the end point for the segment type - int pointIndex = (getNumberOfPoints(type) - 1) * 2; - point[0] = coords[pointIndex]; - point[1] = coords[pointIndex + 1]; - } - - /** - * Returns the number of points stored in a coordinates array for the given segment type. - */ - private static int getNumberOfPoints(int segmentType) { - switch (segmentType) { - case PathIterator.SEG_QUADTO: - return 2; - case PathIterator.SEG_CUBICTO: - return 3; - case PathIterator.SEG_CLOSE: - return 0; - default: - return 1; - } - } - - /** - * Returns the estimated length of a flat path. If the passed path is not flat (i.e. contains a - * segment that is not {@link PathIterator#SEG_CLOSE}, {@link PathIterator#SEG_MOVETO} or {@link - * PathIterator#SEG_LINETO} this method will fail. - */ - private static float getFlatPathLength(@NonNull PathIterator iterator) { - float segment[] = new float[6]; - float totalLength = 0; - float[] previousPoint = new float[2]; - boolean isFirstPoint = true; - - while (!iterator.isDone()) { - int type = iterator.currentSegment(segment); - assert type == PathIterator.SEG_LINETO || type == PathIterator.SEG_CLOSE || type == - PathIterator.SEG_MOVETO; - - // MoveTo shouldn't affect the length - if (!isFirstPoint && type != PathIterator.SEG_MOVETO) { - totalLength += Point2D.distance(previousPoint[0], previousPoint[1], segment[0], - segment[1]); - } else { - isFirstPoint = false; - } - previousPoint[0] = segment[0]; - previousPoint[1] = segment[1]; - iterator.next(); - } - - return totalLength; - } - - /** - * Returns the estimated position along a path of the given length. - */ - private void getPointAtLength(int type, @NonNull float[] coords, float lastX, float - lastY, float t, @NonNull float[] point) { - if (type == PathIterator.SEG_LINETO) { - point[0] = lastX + (coords[0] - lastX) * t; - point[1] = lastY + (coords[1] - lastY) * t; - // Return here, since we do not need a shape to estimate - return; - } - - float[] curve = new float[8]; - int lastPointIndex = (getNumberOfPoints(type) - 1) * 2; - - System.arraycopy(coords, 0, curve, 2, coords.length); - curve[0] = lastX; - curve[1] = lastY; - if (type == PathIterator.SEG_CUBICTO) { - cubicCurveSegment(curve, 0f, t); - } else { - quadCurveSegment(curve, 0f, t); - } - - point[0] = curve[2 + lastPointIndex]; - point[1] = curve[2 + lastPointIndex + 1]; - } - - public CachedPathIterator iterator() { - return new CachedPathIterator(); - } - - /** - * Class that allows us to iterate over a path multiple times - */ - public class CachedPathIterator implements PathIterator { - private int mNextIndex; - - /** - * Current segment type. - * - * @see PathIterator - */ - private int mCurrentType; - - /** - * Stores the coordinates array of the current segment. The number of points stored depends - * on the segment type. - * - * @see PathIterator - */ - private float[] mCurrentCoords = new float[6]; - private float mCurrentSegmentLength; - - /** - * Current segment length offset. When asking for the length of the current segment, the - * length will be reduced by this amount. This is useful when we are only using portions of - * the segment. - * - * @see #jumpToSegment(float) - */ - private float mOffsetLength; - - /** Point where the current segment started */ - private float[] mLastPoint = new float[2]; - private boolean isIteratorDone; - - private CachedPathIterator() { - next(); - } - - public float getCurrentSegmentLength() { - return mCurrentSegmentLength; - } - - @Override - public int getWindingRule() { - return mWindingRule; - } - - @Override - public boolean isDone() { - return isIteratorDone; - } - - @Override - public void next() { - if (mNextIndex >= mTypes.length) { - isIteratorDone = true; - return; - } - - if (mNextIndex >= 1) { - // We've already called next() once so there is a previous segment in this path. - // We want to get the coordinates where the path ends. - getShapeEndPoint(mCurrentType, mCurrentCoords, mLastPoint); - } else { - // This is the first segment, no previous point so initialize to 0, 0 - mLastPoint[0] = mLastPoint[1] = 0f; - } - mCurrentType = mTypes[mNextIndex]; - mCurrentSegmentLength = mSegmentsLength[mNextIndex] - mOffsetLength; - - if (mOffsetLength > 0f && (mCurrentType == SEG_CUBICTO || mCurrentType == SEG_QUADTO)) { - // We need to skip part of the start of the current segment (because - // mOffsetLength > 0) - float[] points = new float[8]; - - if (mNextIndex < 1) { - points[0] = points[1] = 0f; - } else { - getShapeEndPoint(mTypes[mNextIndex - 1], mCoordinates[mNextIndex - 1], points); - } - - System.arraycopy(mCoordinates[mNextIndex], 0, points, 2, - mCoordinates[mNextIndex].length); - float t0 = (mSegmentsLength[mNextIndex] - mCurrentSegmentLength) / - mSegmentsLength[mNextIndex]; - if (mCurrentType == SEG_CUBICTO) { - cubicCurveSegment(points, t0, 1f); - } else { - quadCurveSegment(points, t0, 1f); - } - System.arraycopy(points, 2, mCurrentCoords, 0, mCoordinates[mNextIndex].length); - } else { - System.arraycopy(mCoordinates[mNextIndex], 0, mCurrentCoords, 0, - mCoordinates[mNextIndex].length); - } - - mOffsetLength = 0f; - mNextIndex++; - } - - @Override - public int currentSegment(float[] coords) { - System.arraycopy(mCurrentCoords, 0, coords, 0, getNumberOfPoints(mCurrentType) * 2); - return mCurrentType; - } - - @Override - public int currentSegment(double[] coords) { - throw new UnsupportedOperationException(); - } - - /** - * Returns the point where the current segment ends - */ - public void getCurrentSegmentEnd(float[] point) { - point[0] = mLastPoint[0]; - point[1] = mLastPoint[1]; - } - - /** - * Restarts the iterator and jumps all the segments of this path up to the length value. - */ - public void jumpToSegment(float length) { - isIteratorDone = false; - if (length <= 0f) { - mNextIndex = 0; - return; - } - - float accLength = 0; - float lastPoint[] = new float[2]; - for (mNextIndex = 0; mNextIndex < mTypes.length; mNextIndex++) { - float segmentLength = mSegmentsLength[mNextIndex]; - if (accLength + segmentLength >= length && mTypes[mNextIndex] != SEG_MOVETO) { - float[] estimatedPoint = new float[2]; - getPointAtLength(mTypes[mNextIndex], - mCoordinates[mNextIndex], lastPoint[0], lastPoint[1], - (length - accLength) / segmentLength, - estimatedPoint); - - // This segment makes us go further than length so we go back one step, - // set a moveto and offset the length of the next segment by the length - // of this segment that we've already used. - mCurrentType = PathIterator.SEG_MOVETO; - mCurrentCoords[0] = estimatedPoint[0]; - mCurrentCoords[1] = estimatedPoint[1]; - mCurrentSegmentLength = 0; - - // We need to offset next path length to account for the segment we've just - // skipped. - mOffsetLength = length - accLength; - return; - } - accLength += segmentLength; - getShapeEndPoint(mTypes[mNextIndex], mCoordinates[mNextIndex], lastPoint); - } - } - - /** - * Returns the current segment up to certain length. If the current segment is shorter than - * length, then the whole segment is returned. The segment coordinates are copied into the - * coords array. - * - * @return the segment type - */ - public int currentSegment(@NonNull float[] coords, float length) { - int type = currentSegment(coords); - // If the length is greater than the current segment length, no need to find - // the cut point. Same if this is a SEG_MOVETO. - if (mCurrentSegmentLength <= length || type == SEG_MOVETO) { - return type; - } - - float t = length / getCurrentSegmentLength(); - - // We find at which offset the end point is located within the coords array and set - // a new end point to cut the segment short - switch (type) { - case SEG_CUBICTO: - case SEG_QUADTO: - float[] curve = new float[8]; - curve[0] = mLastPoint[0]; - curve[1] = mLastPoint[1]; - System.arraycopy(coords, 0, curve, 2, coords.length); - if (type == SEG_CUBICTO) { - cubicCurveSegment(curve, 0f, t); - } else { - quadCurveSegment(curve, 0f, t); - } - System.arraycopy(curve, 2, coords, 0, coords.length); - break; - default: - float[] point = new float[2]; - getPointAtLength(type, coords, mLastPoint[0], mLastPoint[1], t, point); - coords[0] = point[0]; - coords[1] = point[1]; - } - - return type; - } - - /** - * Returns the total length of the path - */ - public float getTotalLength() { - return mTotalLength; - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/Debug.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/Debug.java deleted file mode 100644 index 82eab8560acb..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/Debug.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.util; - -public class Debug { - - public final static boolean DEBUG = false; - -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/DynamicIdMap.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/DynamicIdMap.java deleted file mode 100644 index 161bf4155a1a..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/DynamicIdMap.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.util; - -import com.android.resources.ResourceType; -import com.android.util.Pair; - -import android.annotation.NonNull; -import android.util.SparseArray; - -import java.util.HashMap; -import java.util.Map; - -public class DynamicIdMap { - - private final Map<Pair<ResourceType, String>, Integer> mDynamicIds = new HashMap<>(); - private final SparseArray<Pair<ResourceType, String>> mRevDynamicIds = new SparseArray<>(); - private int mDynamicSeed; - - public DynamicIdMap(int seed) { - mDynamicSeed = seed; - } - - public void reset(int seed) { - mDynamicIds.clear(); - mRevDynamicIds.clear(); - mDynamicSeed = seed; - } - - /** - * Returns a dynamic integer for the given resource type/name, creating it if it doesn't - * already exist. - * - * @param type the type of the resource - * @param name the name of the resource - * @return an integer. - */ - @NonNull - public Integer getId(ResourceType type, String name) { - return getId(Pair.of(type, name)); - } - - /** - * Returns a dynamic integer for the given resource type/name, creating it if it doesn't - * already exist. - * - * @param resource the type/name of the resource - * @return an integer. - */ - @NonNull - public Integer getId(Pair<ResourceType, String> resource) { - Integer value = mDynamicIds.get(resource); - if (value == null) { - value = ++mDynamicSeed; - mDynamicIds.put(resource, value); - mRevDynamicIds.put(value, resource); - } - - return value; - } - - public Pair<ResourceType, String> resolveId(int id) { - return mRevDynamicIds.get(id); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/NinePatchInputStream.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/NinePatchInputStream.java deleted file mode 100644 index f149b6cd8ef9..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/NinePatchInputStream.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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 com.android.layoutlib.bridge.util; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; - -/** - * Simpler wrapper around FileInputStream. This is used when the input stream represent - * not a normal bitmap but a nine patch. - * This is useful when the InputStream is created in a method but used in another that needs - * to know whether this is 9-patch or not, such as BitmapFactory. - */ -public class NinePatchInputStream extends FileInputStream { - private boolean mFakeMarkSupport = true; - public NinePatchInputStream(File file) throws FileNotFoundException { - super(file); - } - - @Override - public boolean markSupported() { - // this is needed so that BitmapFactory doesn't wrap this in a BufferedInputStream. - return mFakeMarkSupport || super.markSupported(); - - } - - public void disableFakeMarkSupport() { - // disable fake mark support so that in case codec actually try to use them - // we don't lie to them. - mFakeMarkSupport = false; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/ReflectionUtils.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/ReflectionUtils.java deleted file mode 100644 index b89718ff5ea6..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/ReflectionUtils.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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 com.android.layoutlib.bridge.util; - -import android.annotation.NonNull; -import android.annotation.Nullable; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -/** - * Utility to convert checked Reflection exceptions to unchecked exceptions. - */ -public class ReflectionUtils { - - @NonNull - public static Method getMethod(@NonNull Class<?> clazz, @NonNull String name, - @Nullable Class<?>... params) throws ReflectionException { - try { - return clazz.getMethod(name, params); - } catch (NoSuchMethodException e) { - throw new ReflectionException(e); - } - } - - @NonNull - public static Method getAccessibleMethod(@NonNull Class<?> clazz, @NonNull String name, - @Nullable Class<?>... params) throws ReflectionException { - Method method = getMethod(clazz, name, params); - method.setAccessible(true); - - return method; - } - - @Nullable - public static Object invoke(@NonNull Method method, @Nullable Object object, - @Nullable Object... args) throws ReflectionException { - Exception ex; - try { - return method.invoke(object, args); - } catch (IllegalAccessException | InvocationTargetException e) { - ex = e; - } - throw new ReflectionException(ex); - } - - /** - * Check if the object is an instance of a class named {@code className}. This doesn't work - * for interfaces. - */ - public static boolean isInstanceOf(Object object, String className) { - Class superClass = object.getClass(); - while (superClass != null) { - String name = superClass.getName(); - if (name.equals(className)) { - return true; - } - superClass = superClass.getSuperclass(); - } - return false; - } - - @NonNull - public static Throwable getCause(@NonNull Throwable throwable) { - Throwable cause = throwable.getCause(); - return cause == null ? throwable : cause; - } - - /** - * Looks through the class hierarchy of {@code object} at runtime and returns the class matching - * the name {@code className}. - * <p> - * This is used when we cannot use Class.forName() since the class we want was loaded from a - * different ClassLoader. - */ - @NonNull - public static Class<?> getClassInstance(@NonNull Object object, @NonNull String className) { - Class<?> superClass = object.getClass(); - while (superClass != null) { - if (className.equals(superClass.getName())) { - return superClass; - } - superClass = superClass.getSuperclass(); - } - throw new RuntimeException("invalid object/classname combination."); - } - - /** - * Wraps all reflection related exceptions. Created since ReflectiveOperationException was - * introduced in 1.7 and we are still on 1.6 - */ - public static class ReflectionException extends Exception { - public ReflectionException() { - super(); - } - - public ReflectionException(String message) { - super(message); - } - - public ReflectionException(String message, Throwable cause) { - super(message, cause); - } - - public ReflectionException(Throwable cause) { - super(cause); - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java deleted file mode 100644 index a2a8aa96b155..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.util; - - -import com.android.internal.util.ArrayUtils; -import com.android.internal.util.GrowingArrayUtils; - -import android.util.SparseArray; - -import java.lang.ref.WeakReference; - -/** - * This is a custom {@link SparseArray} that uses {@link WeakReference} around the objects added - * to it. When the array is compacted, not only deleted indices but also empty references - * are removed, making the array efficient at removing references that were reclaimed. - * - * The code is taken from {@link SparseArray} directly and adapted to use weak references. - * - * Because our usage means that we never actually call {@link #remove(long)} or - * {@link #delete(long)}, we must manually check if there are reclaimed references to - * trigger an internal compact step (which is normally only triggered when an item is manually - * removed). - * - * SparseArrays map integral values to Objects. Unlike a normal array of Objects, - * there can be gaps in the indices. It is intended to be more efficient - * than using a HashMap to map Integers (or Longs) to Objects. - */ -@SuppressWarnings("unchecked") -public class SparseWeakArray<E> { - - private static final Object DELETED_REF = new Object(); - private static final WeakReference<?> DELETED = new WeakReference(DELETED_REF); - private boolean mGarbage = false; - - /** - * Creates a new SparseArray containing no mappings. - */ - public SparseWeakArray() { - this(10); - } - - /** - * Creates a new SparseArray containing no mappings that will not - * require any additional memory allocation to store the specified - * number of mappings. - */ - public SparseWeakArray(int initialCapacity) { - mKeys = ArrayUtils.newUnpaddedLongArray(initialCapacity); - mValues = new WeakReference[mKeys.length]; - mSize = 0; - } - - /** - * Gets the Object mapped from the specified key, or <code>null</code> - * if no such mapping has been made. - */ - public E get(long key) { - return get(key, null); - } - - /** - * Gets the Object mapped from the specified key, or the specified Object - * if no such mapping has been made. - */ - public E get(long key, E valueIfKeyNotFound) { - int i = binarySearch(mKeys, 0, mSize, key); - - if (i < 0 || mValues[i] == DELETED || mValues[i].get() == null) { - return valueIfKeyNotFound; - } else { - return (E) mValues[i].get(); - } - } - - /** - * Removes the mapping from the specified key, if there was any. - */ - public void delete(long key) { - int i = binarySearch(mKeys, 0, mSize, key); - - if (i >= 0) { - if (mValues[i] != DELETED) { - mValues[i] = DELETED; - mGarbage = true; - } - } - } - - /** - * Alias for {@link #delete(long)}. - */ - public void remove(long key) { - delete(key); - } - - /** - * Removes the mapping at the specified index. - */ - public void removeAt(int index) { - if (mValues[index] != DELETED) { - mValues[index] = DELETED; - mGarbage = true; - } - } - - private void gc() { - int n = mSize; - int o = 0; - long[] keys = mKeys; - WeakReference<?>[] values = mValues; - - for (int i = 0; i < n; i++) { - WeakReference<?> val = values[i]; - - // Don't keep any non DELETED values, but only the one that still have a valid - // reference. - if (val != DELETED && val.get() != null) { - if (i != o) { - keys[o] = keys[i]; - values[o] = val; - } - - o++; - } - } - - mGarbage = false; - mSize = o; - } - - /** - * Adds a mapping from the specified key to the specified value, - * replacing the previous mapping from the specified key if there - * was one. - */ - public void put(long key, E value) { - int i = binarySearch(mKeys, 0, mSize, key); - - if (i >= 0) { - mValues[i] = new WeakReference(value); - } else { - i = ~i; - - if (i < mSize && (mValues[i] == DELETED || mValues[i].get() == null)) { - mKeys[i] = key; - mValues[i] = new WeakReference(value); - return; - } - - if (mSize >= mKeys.length && (mGarbage || hasReclaimedRefs())) { - gc(); - - // Search again because indices may have changed. - i = ~binarySearch(mKeys, 0, mSize, key); - } - - mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key); - mValues = GrowingArrayUtils.insert(mValues, mSize, i, new WeakReference(value)); - mSize++; - } - } - - /** - * Returns the number of key-value mappings that this SparseArray - * currently stores. - */ - public int size() { - if (mGarbage) { - gc(); - } - - return mSize; - } - - /** - * Given an index in the range <code>0...size()-1</code>, returns - * the key from the <code>index</code>th key-value mapping that this - * SparseArray stores. - */ - public long keyAt(int index) { - if (mGarbage) { - gc(); - } - - return mKeys[index]; - } - - /** - * Given an index in the range <code>0...size()-1</code>, returns - * the value from the <code>index</code>th key-value mapping that this - * SparseArray stores. - */ - public E valueAt(int index) { - if (mGarbage) { - gc(); - } - - return (E) mValues[index].get(); - } - - /** - * Given an index in the range <code>0...size()-1</code>, sets a new - * value for the <code>index</code>th key-value mapping that this - * SparseArray stores. - */ - public void setValueAt(int index, E value) { - if (mGarbage) { - gc(); - } - - mValues[index] = new WeakReference(value); - } - - /** - * Returns the index for which {@link #keyAt} would return the - * specified key, or a negative number if the specified - * key is not mapped. - */ - public int indexOfKey(long key) { - if (mGarbage) { - gc(); - } - - return binarySearch(mKeys, 0, mSize, key); - } - - /** - * Returns an index for which {@link #valueAt} would return the - * specified key, or a negative number if no keys map to the - * specified value. - * Beware that this is a linear search, unlike lookups by key, - * and that multiple keys can map to the same value and this will - * find only one of them. - */ - public int indexOfValue(E value) { - if (mGarbage) { - gc(); - } - - for (int i = 0; i < mSize; i++) - if (mValues[i].get() == value) - return i; - - return -1; - } - - /** - * Removes all key-value mappings from this SparseArray. - */ - public void clear() { - int n = mSize; - WeakReference<?>[] values = mValues; - - for (int i = 0; i < n; i++) { - values[i] = null; - } - - mSize = 0; - mGarbage = false; - } - - /** - * Puts a key/value pair into the array, optimizing for the case where - * the key is greater than all existing keys in the array. - */ - public void append(long key, E value) { - if (mSize != 0 && key <= mKeys[mSize - 1]) { - put(key, value); - return; - } - - if (mSize >= mKeys.length && (mGarbage || hasReclaimedRefs())) { - gc(); - } - - mKeys = GrowingArrayUtils.append(mKeys, mSize, key); - mValues = GrowingArrayUtils.append(mValues, mSize, new WeakReference(value)); - mSize++; - } - - private boolean hasReclaimedRefs() { - for (int i = 0 ; i < mSize ; i++) { - if (mValues[i].get() == null) { // DELETED.get() never returns null. - return true; - } - } - - return false; - } - - private static int binarySearch(long[] a, int start, int len, long key) { - int high = start + len, low = start - 1, guess; - - while (high - low > 1) { - guess = (high + low) / 2; - - if (a[guess] < key) - low = guess; - else - high = guess; - } - - if (high == start + len) - return ~(start + len); - else if (a[high] == key) - return high; - else - return ~high; - } - - private long[] mKeys; - private WeakReference<?>[] mValues; - private int mSize; -} diff --git a/tools/layoutlib/bridge/src/com/google/android/maps/MapView.java b/tools/layoutlib/bridge/src/com/google/android/maps/MapView.java deleted file mode 100644 index 6d013bbe6b05..000000000000 --- a/tools/layoutlib/bridge/src/com/google/android/maps/MapView.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.android.maps; - -import com.android.layoutlib.bridge.MockView; - -import android.content.Context; -import android.os.Bundle; -import android.util.AttributeSet; -import android.view.View; - -/** - * Mock version of the MapView. - * Only non override public methods from the real MapView have been added in there. - * Methods that take an unknown class as parameter or as return object, have been removed for now. - * - * TODO: generate automatically. - * - */ -public class MapView extends MockView { - - /** - * Construct a new WebView with a Context object. - * @param context A Context object used to access application assets. - */ - public MapView(Context context) { - this(context, null); - } - - /** - * Construct a new WebView with layout parameters. - * @param context A Context object used to access application assets. - * @param attrs An AttributeSet passed to our parent. - */ - public MapView(Context context, AttributeSet attrs) { - this(context, attrs, com.android.internal.R.attr.mapViewStyle); - } - - /** - * Construct a new WebView with layout parameters and a default style. - * @param context A Context object used to access application assets. - * @param attrs An AttributeSet passed to our parent. - * @param defStyle The default style resource ID. - */ - public MapView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - // START FAKE PUBLIC METHODS - - public void displayZoomControls(boolean takeFocus) { - } - - public boolean canCoverCenter() { - return false; - } - - public void preLoad() { - } - - public int getZoomLevel() { - return 0; - } - - public void setSatellite(boolean on) { - } - - public boolean isSatellite() { - return false; - } - - public void setTraffic(boolean on) { - } - - public boolean isTraffic() { - return false; - } - - public void setStreetView(boolean on) { - } - - public boolean isStreetView() { - return false; - } - - public int getLatitudeSpan() { - return 0; - } - - public int getLongitudeSpan() { - return 0; - } - - public int getMaxZoomLevel() { - return 0; - } - - public void onSaveInstanceState(Bundle state) { - } - - public void onRestoreInstanceState(Bundle state) { - } - - public View getZoomControls() { - return null; - } -} diff --git a/tools/layoutlib/bridge/src/dalvik/system/VMRuntime_Delegate.java b/tools/layoutlib/bridge/src/dalvik/system/VMRuntime_Delegate.java deleted file mode 100644 index 36efc3a27479..000000000000 --- a/tools/layoutlib/bridge/src/dalvik/system/VMRuntime_Delegate.java +++ /dev/null @@ -1,78 +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 dalvik.system; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate used to provide implementation of a select few native methods of {@link VMRuntime} - * <p/> - * Through the layoutlib_create tool, the original native methods of VMRuntime have been replaced - * by calls to methods of the same name in this delegate class. - */ -public class VMRuntime_Delegate { - - // Copied from libcore/libdvm/src/main/java/dalvik/system/VMRuntime - @LayoutlibDelegate - /*package*/ static Object newUnpaddedArray(VMRuntime runtime, Class<?> componentType, - int minLength) { - // Dalvik has 32bit pointers, the array header is 16bytes plus 4bytes for dlmalloc, - // allocations are 8byte aligned so having 4bytes of array data avoids padding. - if (!componentType.isPrimitive()) { - int size = ((minLength & 1) == 0) ? minLength + 1 : minLength; - return java.lang.reflect.Array.newInstance(componentType, size); - } else if (componentType == char.class) { - int bytes = 20 + (2 * minLength); - int alignedUpBytes = (bytes + 7) & -8; - int dataBytes = alignedUpBytes - 20; - int size = dataBytes / 2; - return new char[size]; - } else if (componentType == int.class) { - int size = ((minLength & 1) == 0) ? minLength + 1 : minLength; - return new int[size]; - } else if (componentType == byte.class) { - int bytes = 20 + minLength; - int alignedUpBytes = (bytes + 7) & -8; - int dataBytes = alignedUpBytes - 20; - int size = dataBytes; - return new byte[size]; - } else if (componentType == boolean.class) { - int bytes = 20 + minLength; - int alignedUpBytes = (bytes + 7) & -8; - int dataBytes = alignedUpBytes - 20; - int size = dataBytes; - return new boolean[size]; - } else if (componentType == short.class) { - int bytes = 20 + (2 * minLength); - int alignedUpBytes = (bytes + 7) & -8; - int dataBytes = alignedUpBytes - 20; - int size = dataBytes / 2; - return new short[size]; - } else if (componentType == float.class) { - int size = ((minLength & 1) == 0) ? minLength + 1 : minLength; - return new float[size]; - } else if (componentType == long.class) { - return new long[minLength]; - } else if (componentType == double.class) { - return new double[minLength]; - } else { - assert componentType == void.class; - throw new IllegalArgumentException("Can't allocate an array of void"); - } - } - -} diff --git a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java deleted file mode 100644 index 9c5801080e17..000000000000 --- a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright (C) 2011 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 com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.icu.text.DateTimePatternGenerator; -import android.icu.util.Currency; -import android.icu.util.ULocale; -import android.icu.util.VersionInfo; - -import java.util.Locale; - -/** - * Delegate implementing the native methods of libcore.icu.ICU - * - * Through the layoutlib_create tool, the original native methods of ICU have been replaced - * by calls to methods of the same name in this delegate class. - * - */ -public class ICU_Delegate { - - // --- Java delegates - - @LayoutlibDelegate - /*package*/ static String toLowerCase(String s, String localeName) { - return s.toLowerCase(); - } - - @LayoutlibDelegate - /*package*/ static String toUpperCase(String s, String localeName) { - return s.toUpperCase(); - } - - // --- Native methods accessing ICU's database. - - @LayoutlibDelegate - /*package*/ static String getBestDateTimePatternNative(String skeleton, String localeName) { - return DateTimePatternGenerator.getInstance(new ULocale(localeName)) - .getBestPattern(skeleton); - } - - @LayoutlibDelegate - @SuppressWarnings("deprecation") - /*package*/ static String getCldrVersion() { - return VersionInfo.ICU_DATA_VERSION.toString(); - } - - @LayoutlibDelegate - /*package*/ static String getIcuVersion() { - return VersionInfo.ICU_VERSION.toString(); - } - - @LayoutlibDelegate - /*package*/ static String getUnicodeVersion() { - return VersionInfo.UNICODE_7_0.toString(); - } - - @LayoutlibDelegate - /*package*/ static String[] getAvailableBreakIteratorLocalesNative() { - return new String[0]; - } - - @LayoutlibDelegate - /*package*/ static String[] getAvailableCalendarLocalesNative() { - return new String[0]; - } - - @LayoutlibDelegate - /*package*/ static String[] getAvailableCollatorLocalesNative() { - return new String[0]; - } - - @LayoutlibDelegate - /*package*/ static String[] getAvailableDateFormatLocalesNative() { - return new String[0]; - } - - @LayoutlibDelegate - /*package*/ static String[] getAvailableLocalesNative() { - return new String[0]; - } - - @LayoutlibDelegate - /*package*/ static String[] getAvailableNumberFormatLocalesNative() { - return new String[0]; - } - - @LayoutlibDelegate - /*package*/ static String[] getAvailableCurrencyCodes() { - return new String[0]; - } - - @LayoutlibDelegate - /*package*/ static String getCurrencyCode(String locale) { - return ""; - } - - @LayoutlibDelegate - /*package*/ static String getCurrencyDisplayName(String locale, String currencyCode) { - return ""; - } - - @LayoutlibDelegate - /*package*/ static int getCurrencyFractionDigits(String currencyCode) { - return 0; - } - - @LayoutlibDelegate - /*package*/ static int getCurrencyNumericCode(String currencyCode) { - return Currency.getInstance(currencyCode).getNumericCode(); - } - - @LayoutlibDelegate - /*package*/ static String getCurrencySymbol(String locale, String currencyCode) { - return ""; - } - - @LayoutlibDelegate - /*package*/ static String getDisplayCountryNative(String countryCode, String locale) { - return ""; - } - - @LayoutlibDelegate - /*package*/ static String getDisplayLanguageNative(String languageCode, String locale) { - return ""; - } - - @LayoutlibDelegate - /*package*/ static String getDisplayVariantNative(String variantCode, String locale) { - return ""; - } - - @LayoutlibDelegate - /*package*/ static String getDisplayScriptNative(String variantCode, String locale) { - return ""; - } - - @LayoutlibDelegate - /*package*/ static String getISO3Country(String locale) { - return ""; - } - - @LayoutlibDelegate - /*package*/ static String getISO3Language(String locale) { - return ""; - } - - @LayoutlibDelegate - /*package*/ static String addLikelySubtags(String locale) { - return ""; - } - - @LayoutlibDelegate - /*package*/ static String getScript(String locale) { - return ""; - } - - @LayoutlibDelegate - /*package*/ static String[] getISOLanguagesNative() { - return Locale.getISOLanguages(); - } - - @LayoutlibDelegate - /*package*/ static String[] getISOCountriesNative() { - return Locale.getISOCountries(); - } - - @LayoutlibDelegate - /*package*/ static boolean initLocaleDataNative(String locale, LocaleData result) { - - // Used by Calendar. - result.firstDayOfWeek = 1; - result.minimalDaysInFirstWeek = 1; - - // Used by DateFormatSymbols. - result.amPm = new String[] { "AM", "PM" }; - result.eras = new String[] { "BC", "AD" }; - - result.longMonthNames = new String[] { "January", "February", "March", "April", "May", - "June", "July", "August", "September", "October", "November", "December" }; - result.shortMonthNames = new String[] { "Jan", "Feb", "Mar", "Apr", "May", - "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - result.longStandAloneMonthNames = result.longMonthNames; - result.shortStandAloneMonthNames = result.shortMonthNames; - - // The platform code expects this to begin at index 1, rather than 0. It maps it directly to - // the constants from java.util.Calendar.<weekday> - result.longWeekdayNames = new String[] { - "", "Sunday", "Monday" ,"Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; - result.shortWeekdayNames = new String[] { - "", "Sun", "Mon" ,"Tue", "Wed", "Thu", "Fri", "Sat" }; - result.tinyWeekdayNames = new String[] { - "", "S", "M", "T", "W", "T", "F", "S" }; - - result.longStandAloneWeekdayNames = result.longWeekdayNames; - result.shortStandAloneWeekdayNames = result.shortWeekdayNames; - result.tinyStandAloneWeekdayNames = result.tinyWeekdayNames; - - result.fullTimeFormat = ""; - result.longTimeFormat = ""; - result.mediumTimeFormat = ""; - result.shortTimeFormat = ""; - - result.fullDateFormat = ""; - result.longDateFormat = ""; - result.mediumDateFormat = ""; - result.shortDateFormat = ""; - - // Used by DecimalFormatSymbols. - result.zeroDigit = '0'; - result.decimalSeparator = '.'; - result.groupingSeparator = ','; - result.patternSeparator = ' '; - result.percent = "%"; - result.perMill = '\u2030'; - result.monetarySeparator = ' '; - result.minusSign = "-"; - result.exponentSeparator = "e"; - result.infinity = "\u221E"; - result.NaN = "NaN"; - // Also used by Currency. - result.currencySymbol = "$"; - result.internationalCurrencySymbol = "USD"; - - // Used by DecimalFormat and NumberFormat. - result.numberPattern = "%f"; - result.integerPattern = "%d"; - result.currencyPattern = "%s"; - result.percentPattern = "%f"; - - return true; - } - - @LayoutlibDelegate - /*package*/ static void setDefaultLocale(String locale) { - ICU.setDefaultLocale(locale); - } - - @LayoutlibDelegate - /*package*/ static String getDefaultLocale() { - return ICU.getDefaultLocale(); - } - - @LayoutlibDelegate - /*package*/ static String getTZDataVersion() { - return ICU.getTZDataVersion(); - } -} diff --git a/tools/layoutlib/bridge/src/libcore/io/MemoryMappedFile_Delegate.java b/tools/layoutlib/bridge/src/libcore/io/MemoryMappedFile_Delegate.java deleted file mode 100644 index 723d5c4b0d0c..000000000000 --- a/tools/layoutlib/bridge/src/libcore/io/MemoryMappedFile_Delegate.java +++ /dev/null @@ -1,118 +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 libcore.io; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.layoutlib.bridge.libcore.io.BridgeBufferIterator; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.system.ErrnoException; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteOrder; -import java.nio.MappedByteBuffer; -import java.nio.channels.FileChannel.MapMode; -import java.util.HashMap; -import java.util.Map; - -/** - * Delegate used to provide alternate implementation of select methods of {@link MemoryMappedFile}. - */ -public class MemoryMappedFile_Delegate { - - private static final DelegateManager<MemoryMappedFile_Delegate> sManager = new - DelegateManager<MemoryMappedFile_Delegate>(MemoryMappedFile_Delegate.class); - - private static final Map<MemoryMappedFile, Long> sMemoryMappedFileMap = - new HashMap<MemoryMappedFile, Long>(); - - private final MappedByteBuffer mMappedByteBuffer; - private final long mSize; - - /** Path on the target device where the data file is available. */ - private static final String TARGET_PATH = System.getenv("ANDROID_ROOT") + "/usr/share/zoneinfo"; - /** Path on the host (inside the SDK) where the data files are available. */ - private static File sRootPath; - - @LayoutlibDelegate - static MemoryMappedFile mmapRO(String path) throws ErrnoException { - if (!path.startsWith(TARGET_PATH)) { - throw new ErrnoException("Custom timezone data files are not supported.", 1); - } - if (sRootPath == null) { - throw new ErrnoException("Bridge has not been initialized properly.", 1); - } - path = path.substring(TARGET_PATH.length()); - try { - File f = new File(sRootPath, path); - if (!f.exists()) { - throw new ErrnoException("File not found: " + f.getPath(), 1); - } - RandomAccessFile file = new RandomAccessFile(f, "r"); - try { - long size = file.length(); - MemoryMappedFile_Delegate newDelegate = new MemoryMappedFile_Delegate(file); - long filePointer = file.getFilePointer(); - MemoryMappedFile mmFile = new MemoryMappedFile(filePointer, size); - long delegateIndex = sManager.addNewDelegate(newDelegate); - sMemoryMappedFileMap.put(mmFile, delegateIndex); - return mmFile; - } finally { - file.close(); - } - } catch (IOException e) { - throw new ErrnoException("mmapRO", 1, e); - } - } - - @LayoutlibDelegate - static void close(MemoryMappedFile thisFile) throws ErrnoException { - Long index = sMemoryMappedFileMap.get(thisFile); - if (index != null) { - sMemoryMappedFileMap.remove(thisFile); - sManager.removeJavaReferenceFor(index); - } - } - - @LayoutlibDelegate - static BufferIterator bigEndianIterator(MemoryMappedFile file) { - MemoryMappedFile_Delegate delegate = getDelegate(file); - return new BridgeBufferIterator(delegate.mSize, delegate.mMappedByteBuffer.duplicate()); - } - - // TODO: implement littleEndianIterator() - - public MemoryMappedFile_Delegate(RandomAccessFile file) throws IOException { - mSize = file.length(); - // It's weird that map() takes size as long, but returns MappedByteBuffer which uses an int - // to store the marker to the position. - mMappedByteBuffer = file.getChannel().map(MapMode.READ_ONLY, 0, mSize); - assert mMappedByteBuffer.order() == ByteOrder.BIG_ENDIAN; - } - - public static void setDataDir(File path) { - sRootPath = path; - } - - private static MemoryMappedFile_Delegate getDelegate(MemoryMappedFile file) { - Long index = sMemoryMappedFileMap.get(file); - return index == null ? null : sManager.getDelegate(index); - } - -} diff --git a/tools/layoutlib/bridge/src/libcore/util/NativeAllocationRegistry_Delegate.java b/tools/layoutlib/bridge/src/libcore/util/NativeAllocationRegistry_Delegate.java deleted file mode 100644 index 04fabc242454..000000000000 --- a/tools/layoutlib/bridge/src/libcore/util/NativeAllocationRegistry_Delegate.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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) { - // This method MIGHT run in the context of the finalizer thread. If the delegate method - // crashes, it could bring down the VM. That's why we catch all the exceptions and ignore - // them. - try { - NativeAllocationRegistry_Delegate delegate = sManager.getDelegate(freeFunction); - if (delegate != null) { - delegate.mFinalizer.free(nativePtr); - } - } catch (Throwable ignore) { - } - } - - public interface FreeFunction { - void free(long nativePtr); - } -} |