Skip to content

Commit

Permalink
Add set/get ColorFilter to Drawable and ImageView
Browse files Browse the repository at this point in the history
Add ImageView.setImageTintBlendMode
Review ImageDrawable.setSrcRect method
  • Loading branch information
BloCamLimb committed Aug 25, 2024
1 parent 742c7a5 commit 7983868
Show file tree
Hide file tree
Showing 3 changed files with 242 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import icyllis.modernui.view.View;
import icyllis.modernui.widget.ImageView;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.UnmodifiableView;

import java.lang.ref.WeakReference;
import java.util.Arrays;
Expand Down Expand Up @@ -193,6 +194,7 @@ public final Rect copyBounds() {
* @see #copyBounds()
* @see #copyBounds(Rect)
*/
@UnmodifiableView
@NonNull
public final Rect getBounds() {
if (mBounds == ZERO_BOUNDS_RECT) {
Expand Down Expand Up @@ -391,7 +393,7 @@ protected boolean onLayoutDirectionChanged(@View.ResolvedLayoutDir int layoutDir
* Specify an alpha value for the drawable. 0 means fully transparent, and
* 255 means fully opaque.
*/
public void setAlpha(int alpha) {
public void setAlpha(@IntRange(from = 0, to = 255) int alpha) {
}

/**
Expand All @@ -409,8 +411,16 @@ public int getAlpha() {
/**
* Specifies tint color for this drawable.
* <p>
* A Drawable's drawing content will be blended together with its tint
* before it is drawn to the screen.
* </p>
* <p>
* To clear the tint, pass {@code null} to
* {@link #setTintList(ColorStateList)}.
* </p>
* <p class="note"><strong>Note:</strong> Setting a color filter via
* {@link #setColorFilter(ColorFilter)} overrides tint.
* </p>
*
* @param tintColor Color to use for tinting this drawable
* @see #setTintList(ColorStateList)
Expand All @@ -422,6 +432,13 @@ public void setTint(@ColorInt int tintColor) {

/**
* Specifies tint color for this drawable as a color state list.
* <p>
* A Drawable's drawing content will be blended together with its tint
* before it is drawn to the screen.
* </p>
* <p class="note"><strong>Note:</strong> Setting a color filter via
* {@link #setColorFilter(ColorFilter)} overrides tint.
* </p>
*
* @param tint Color state list to use for tinting this drawable, or
* {@code null} to clear the tint
Expand All @@ -436,14 +453,49 @@ public void setTintList(@Nullable ColorStateList tint) {
* <p>
* Defines how this drawable's tint color should be blended into the drawable
* before it is drawn to screen. Default tint mode is {@link BlendMode#SRC_IN}.
* </p>
* <p class="note"><strong>Note:</strong> Setting a color filter via
* {@link #setColorFilter(ColorFilter)}
* </p>
*
* @param blendMode BlendMode to apply to the drawable
* @param blendMode BlendMode to apply to the drawable, a value of null sets the default
* blend mode value of {@link BlendMode#SRC_IN}
* @see #setTint(int)
* @see #setTintList(ColorStateList)
*/
public void setTintBlendMode(@NonNull BlendMode blendMode) {
}

/**
* Specify an optional color filter for the drawable.
* <p>
* If a Drawable has a ColorFilter, each output pixel of the Drawable's
* drawing contents will be modified by the color filter before it is
* blended onto the render target of a Canvas.
* </p>
* <p>
* Pass {@code null} to remove any existing color filter.
* </p>
* <p class="note"><strong>Note:</strong> Setting a non-{@code null} color
* filter disables {@link #setTintList(ColorStateList) tint}.
* </p>
*
* @param colorFilter The color filter to apply, or {@code null} to remove the
* existing color filter
*/
public void setColorFilter(@Nullable ColorFilter colorFilter) {
}

/**
* Returns the current color filter, or {@code null} if none set.
*
* @return the current color filter, or {@code null} if none set
*/
@Nullable
public ColorFilter getColorFilter() {
return null;
}

/**
* Specifies the hotspot's location within the drawable.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,16 @@ public final Image getImage() {
}

/**
* Switch to a new Image object.
* Switch to a new Image object. Calling this method will also reset
* the subset to the full image, see {@link #setSrcRect(Rect)}.
*/
public void setImage(@Nullable Image image) {
if (mImageState.mImage != image) {
mImageState.mImage = image;
if (mSrcRect != null && image != null) {
mSrcRect.set(0, 0, image.getWidth(), image.getWidth());
}
mFullImage = true;
invalidateSelf();
}
}
Expand Down Expand Up @@ -134,43 +139,83 @@ public void setGravity(int gravity) {
* Specifies the subset of the image to draw. To draw the full image,
* call {@link #setSrcRect(Rect)} with null.
* <p>
* Caveat: this method is marked experimental since 3.11 and may be redesigned
* in the future releases.
* Calling this method when there's no image has no effect. Next call
* to {@link #setImage(Image)} will reset the subset to the full image.
*/
@ApiStatus.Experimental
public void setSrcRect(int left, int top, int right, int bottom) {
if (mSrcRect == null) {
mSrcRect = new Rect(left, top, right, bottom);
invalidateSelf();
final Image image = mImageState.mImage;
if (image == null) {
return;
}
int imageWidth = image.getWidth();
int imageHeight = image.getHeight();
if (left <= 0 && top <= 0 &&
right >= imageWidth && bottom >= imageHeight) {
if (!mFullImage) {
invalidateSelf();
}
mFullImage = true;
} else {
Rect oldBounds = mSrcRect;
if (oldBounds.left != left || oldBounds.top != top ||
oldBounds.right != right || oldBounds.bottom != bottom) {
mSrcRect.set(left, top, right, bottom);
if (mSrcRect == null) {
mSrcRect = new Rect(0, 0, imageWidth, imageHeight);
if (!mSrcRect.intersect(left, top, right, bottom)) {
mSrcRect.setEmpty();
}
invalidateSelf();
} else {
Rect oldBounds = mSrcRect;
if (oldBounds.left != left || oldBounds.top != top ||
oldBounds.right != right || oldBounds.bottom != bottom) {
mSrcRect.set(0, 0, imageWidth, imageHeight);
if (!mSrcRect.intersect(left, top, right, bottom)) {
mSrcRect.setEmpty();
}
invalidateSelf();
}
}
mFullImage = false;
}
mFullImage = false;
}

/**
* Specifies the subset of the image to draw. Null for the full image.
* <p>
* Calling this method when there's no image has no effect. Next call
* to {@link #setImage(Image)} will reset the subset to the full image.
*
* @param srcRect the subset of the image
*/
@ApiStatus.Experimental
public void setSrcRect(@Nullable Rect srcRect) {
if (srcRect == null) {
final Image image = mImageState.mImage;
if (image == null) {
return;
}
int imageWidth = image.getWidth();
int imageHeight = image.getHeight();
if (srcRect == null || (srcRect.left <= 0 && srcRect.top <= 0 &&
srcRect.right >= imageWidth && srcRect.bottom >= imageHeight)) {
if (!mFullImage) {
invalidateSelf();
}
mFullImage = true;
} else {
if (mSrcRect == null) {
mSrcRect = srcRect.copy();
mSrcRect = new Rect(0, 0, imageWidth, imageHeight);
if (!mSrcRect.intersect(srcRect)) {
mSrcRect.setEmpty();
}
invalidateSelf();
} else {
mSrcRect.set(srcRect);
if (!mSrcRect.equals(srcRect)) {
mSrcRect.set(0, 0, imageWidth, imageHeight);
if (!mSrcRect.intersect(srcRect)) {
mSrcRect.setEmpty();
}
invalidateSelf();
}
}
mFullImage = false;
}
invalidateSelf();
}

/**
Expand All @@ -181,6 +226,7 @@ public void setSrcRect(@Nullable Rect srcRect) {
* @param mipmap True if the image should use mipmaps, false otherwise.
* @see #hasMipmap()
*/
@ApiStatus.Experimental
public void setMipmap(boolean mipmap) {
}

Expand All @@ -191,6 +237,7 @@ public void setMipmap(boolean mipmap) {
* is null, this method always returns false.
* @see #setMipmap(boolean)
*/
@ApiStatus.Experimental
public boolean hasMipmap() {
return true;
}
Expand Down Expand Up @@ -503,6 +550,18 @@ public void setTintBlendMode(@NonNull BlendMode blendMode) {
}
}

@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
mImageState.mPaint.setColorFilter(colorFilter);
invalidateSelf();
}

@Nullable
@Override
public ColorFilter getColorFilter() {
return mImageState.mPaint.getColorFilter();
}

/**
* A mutable ImageDrawable still shares its Image with any other Drawable
* that comes from the same resource.
Expand Down
Loading

0 comments on commit 7983868

Please sign in to comment.