/**
  * Updates the overlay-color rounding of the parent's child drawable.
  *
  * <ul>
  *   <li>If rounding mode is OVERLAY_COLOR and the child is not a RoundedCornersDrawable, a new
  *       RoundedCornersDrawable is created and the child gets wrapped with it.
  *   <li>If rounding mode is OVERLAY_COLOR and the child is already wrapped with a
  *       RoundedCornersDrawable, its rounding parameters are updated.
  *   <li>If rounding mode is not OVERLAY_COLOR and the child is wrapped with a
  *       RoundedCornersDrawable, the rounded drawable gets removed and its child gets attached
  *       directly to the parent.
  * </ul>
  */
 static void updateOverlayColorRounding(
     DrawableParent parent, @Nullable RoundingParams roundingParams) {
   Drawable child = parent.getDrawable();
   if (roundingParams != null
       && roundingParams.getRoundingMethod() == RoundingParams.RoundingMethod.OVERLAY_COLOR) {
     // Overlay rounding requested - either update the overlay params or add a new
     // drawable that will do the requested rounding.
     if (child instanceof RoundedCornersDrawable) {
       RoundedCornersDrawable roundedCornersDrawable = (RoundedCornersDrawable) child;
       applyRoundingParams(roundedCornersDrawable, roundingParams);
       roundedCornersDrawable.setOverlayColor(roundingParams.getOverlayColor());
     } else {
       // Important: remove the child before wrapping it with a new parent!
       child = parent.setDrawable(sEmptyDrawable);
       child = maybeWrapWithRoundedOverlayColor(child, roundingParams);
       parent.setDrawable(child);
     }
   } else if (child instanceof RoundedCornersDrawable) {
     // Overlay rounding no longer required so remove drawable that was doing the rounding.
     RoundedCornersDrawable roundedCornersDrawable = (RoundedCornersDrawable) child;
     // Important: remove the child before wrapping it with a new parent!
     child = roundedCornersDrawable.setCurrent(sEmptyDrawable);
     parent.setDrawable(child);
     // roundedCornersDrawable is removed and will get garbage collected, clear the child callback
     sEmptyDrawable.setCallback(null);
   }
 }
 /** Wraps the parent's child with a ScaleTypeDrawable. */
 static ScaleTypeDrawable wrapChildWithScaleType(DrawableParent parent, ScaleType scaleType) {
   Drawable child = parent.setDrawable(sEmptyDrawable);
   child = maybeWrapWithScaleType(child, scaleType);
   parent.setDrawable(child);
   Preconditions.checkNotNull(child, "Parent has no child drawable!");
   return (ScaleTypeDrawable) child;
 }
 /**
  * Applies rounding on the drawable's leaf.
  *
  * <p>Currently only {@link BitmapDrawable} or {@link ColorDrawable} leafs can be rounded.
  *
  * <p>If the leaf cannot be rounded, or the rounding params do not specify BITMAP_ONLY mode, the
  * given drawable is returned without being rounded.
  *
  * <p>If the given drawable is a leaf itself, and it can be rounded, then the rounded drawable is
  * returned.
  *
  * <p>If the given drawable is not a leaf, and its leaf can be rounded, the leaf gets rounded, and
  * the original drawable is returned.
  *
  * @return the rounded drawable, or the original drawable if the rounding didn't take place or it
  *     took place on a drawable's child
  */
 static Drawable maybeApplyLeafRounding(
     @Nullable Drawable drawable, @Nullable RoundingParams roundingParams, Resources resources) {
   if (drawable == null
       || roundingParams == null
       || roundingParams.getRoundingMethod() != RoundingParams.RoundingMethod.BITMAP_ONLY) {
     return drawable;
   }
   if (drawable instanceof ForwardingDrawable) {
     DrawableParent parent = findDrawableParentForLeaf((ForwardingDrawable) drawable);
     Drawable child = parent.setDrawable(sEmptyDrawable);
     child = applyLeafRounding(child, roundingParams, resources);
     parent.setDrawable(child);
     return drawable;
   } else {
     return applyLeafRounding(drawable, roundingParams, resources);
   }
 }
 /** Finds the immediate parent of a leaf drawable. */
 static DrawableParent findDrawableParentForLeaf(DrawableParent parent) {
   while (true) {
     Drawable child = parent.getDrawable();
     if (child == parent || !(child instanceof DrawableParent)) {
       break;
     }
     parent = (DrawableParent) child;
   }
   return parent;
 }
 /**
  * Updates the leaf rounding of the parent's child drawable.
  *
  * <ul>
  *   <li>If rounding mode is BITMAP_ONLY and the child is not a rounded drawable, it gets rounded
  *       with a new rounded drawable.
  *   <li>If rounding mode is BITMAP_ONLY and the child is already rounded, its rounding parameters
  *       are updated.
  *   <li>If rounding mode is not BITMAP_ONLY and the child is rounded, its rounding parameters are
  *       reset so that no rounding occurs.
  * </ul>
  */
 static void updateLeafRounding(
     DrawableParent parent, @Nullable RoundingParams roundingParams, Resources resources) {
   parent = findDrawableParentForLeaf(parent);
   Drawable child = parent.getDrawable();
   if (roundingParams != null
       && roundingParams.getRoundingMethod() == RoundingParams.RoundingMethod.BITMAP_ONLY) {
     // Leaf rounding requested - either update the params or wrap the current drawable in a
     // drawable that will round it.
     if (child instanceof Rounded) {
       Rounded rounded = (Rounded) child;
       applyRoundingParams(rounded, roundingParams);
     } else if (child != null) {
       // Important: remove the child before wrapping it with a new parent!
       parent.setDrawable(sEmptyDrawable);
       Drawable rounded = applyLeafRounding(child, roundingParams, resources);
       parent.setDrawable(rounded);
     }
   } else if (child instanceof Rounded) {
     // No rounding requested - reset rounding params so no rounding occurs.
     resetRoundingParams((Rounded) child);
   }
 }