/* * 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; } }