1df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata/*
2df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata * Copyright (C) 2015 The Android Open Source Project
3df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata *
4df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata * Licensed under the Apache License, Version 2.0 (the "License");
5df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata * you may not use this file except in compliance with the License.
6df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata * You may obtain a copy of the License at
7df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata *
8df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata *      http://www.apache.org/licenses/LICENSE-2.0
9df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata *
10df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata * Unless required by applicable law or agreed to in writing, software
11df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata * distributed under the License is distributed on an "AS IS" BASIS,
12df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata * See the License for the specific language governing permissions and
14df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata * limitations under the License.
15df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata */
16ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.leanback.graphics;
17df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
18df64e524a2bad079e6b0aa2d22c287f2c62aed82susnataimport android.graphics.Bitmap;
19df64e524a2bad079e6b0aa2d22c287f2c62aed82susnataimport android.graphics.Canvas;
20df64e524a2bad079e6b0aa2d22c287f2c62aed82susnataimport android.graphics.ColorFilter;
213d9017263a760990ba79d5ebf3d1b6587e0bd311susnataimport android.graphics.Paint;
22df64e524a2bad079e6b0aa2d22c287f2c62aed82susnataimport android.graphics.PixelFormat;
23df64e524a2bad079e6b0aa2d22c287f2c62aed82susnataimport android.graphics.Rect;
243d9017263a760990ba79d5ebf3d1b6587e0bd311susnataimport android.graphics.drawable.Drawable;
25e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Guimport android.os.Build;
26e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Guimport android.util.IntProperty;
27e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Guimport android.util.Property;
28df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
298619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.annotation.NonNull;
308619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.annotation.RequiresApi;
318619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikas
32df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata/**
333d9017263a760990ba79d5ebf3d1b6587e0bd311susnata * Subclass of {@link Drawable} that can be used to draw a bitmap into a region. Bitmap
34df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata * will be scaled to fit the full width of the region and will be aligned to the top left corner.
35df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata * Any region outside the bounds will be clipped during {@link #draw(Canvas)} call. Top
36e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * position of the bitmap can be controlled by {@link #setVerticalOffset(int)} call or
37e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * {@link #PROPERTY_VERTICAL_OFFSET}.
38df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata */
393d9017263a760990ba79d5ebf3d1b6587e0bd311susnatapublic class FitWidthBitmapDrawable extends Drawable {
40df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
4100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    static class BitmapState extends Drawable.ConstantState {
4200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        Paint mPaint;
4300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        Bitmap mBitmap;
4400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        Rect mSource;
4500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        final Rect mDefaultSource = new Rect();
4600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        int mOffset;
4700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
4800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        BitmapState() {
4900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            mPaint = new Paint();
5000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        }
5100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
5200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        BitmapState(BitmapState other) {
5300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            mBitmap = other.mBitmap;
5400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            mPaint = new Paint(other.mPaint);
5500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            mSource = other.mSource != null ? new Rect(other.mSource) : null;
5600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            mDefaultSource.set(other.mDefaultSource);
5700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            mOffset = other.mOffset;
5800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        }
5900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
6000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        @NonNull
6100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        @Override
6200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        public Drawable newDrawable() {
6300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            return new FitWidthBitmapDrawable(this);
6400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        }
6500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
6600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        @Override
6700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        public int getChangingConfigurations() {
6800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            return 0;
6900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        }
7000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    }
7100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
7200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    final Rect mDest = new Rect();
7300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    BitmapState mBitmapState;
7400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    boolean mMutated = false;
7500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
76935b033edfd9d03129fce6a5b7a1d3a327b74f91susnata    public FitWidthBitmapDrawable() {
7700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        mBitmapState = new BitmapState();
7800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    }
7900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
8000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    FitWidthBitmapDrawable(BitmapState state) {
8100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        mBitmapState = state;
8200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    }
8300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
8400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    @Override
8500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    public ConstantState getConstantState() {
8600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        return mBitmapState;
8700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    }
8800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
8900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    @Override
9000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    public Drawable mutate() {
9100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        if (!mMutated && super.mutate() == this) {
9200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            mBitmapState = new BitmapState(mBitmapState);
9300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            mMutated = true;
9400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        }
9500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        return this;
96df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
97df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
98df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    /**
99df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata     * Sets the bitmap.
100df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata     */
101df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    public void setBitmap(Bitmap bitmap) {
10200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        mBitmapState.mBitmap = bitmap;
103935b033edfd9d03129fce6a5b7a1d3a327b74f91susnata        if (bitmap != null) {
10400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            mBitmapState.mDefaultSource.set(0, 0, bitmap.getWidth(), bitmap.getHeight());
105935b033edfd9d03129fce6a5b7a1d3a327b74f91susnata        } else {
10600f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            mBitmapState.mDefaultSource.set(0, 0, 0, 0);
107935b033edfd9d03129fce6a5b7a1d3a327b74f91susnata        }
10800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        mBitmapState.mSource = null;
109df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
110df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
111df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    /**
112df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata     * Returns the bitmap.
113df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata     */
114df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    public Bitmap getBitmap() {
11500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        return mBitmapState.mBitmap;
116df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
117df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
118df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    /**
119df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata     * Sets the {@link Rect} used for extracting the bitmap.
120df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata     */
121df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    public void setSource(Rect source) {
12200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        mBitmapState.mSource = source;
123df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
124df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
125df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    /**
126df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata     * Returns the {@link Rect} used for extracting the bitmap.
127df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata     */
128df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    public Rect getSource() {
12900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        return mBitmapState.mSource;
130df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
131df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
132df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    /**
133df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata     * Sets the vertical offset which will be used for drawing the bitmap. The bitmap drawing
134df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata     * will start the provided vertical offset.
135e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @see #PROPERTY_VERTICAL_OFFSET
136df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata     */
137df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    public void setVerticalOffset(int offset) {
13800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        mBitmapState.mOffset = offset;
139df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata        invalidateSelf();
140df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
141df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
1423d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    /**
1433d9017263a760990ba79d5ebf3d1b6587e0bd311susnata     * Returns the current vertical offset.
144e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @see #PROPERTY_VERTICAL_OFFSET
1453d9017263a760990ba79d5ebf3d1b6587e0bd311susnata     */
1463d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    public int getVerticalOffset() {
14700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        return mBitmapState.mOffset;
1483d9017263a760990ba79d5ebf3d1b6587e0bd311susnata    }
1493d9017263a760990ba79d5ebf3d1b6587e0bd311susnata
150df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    @Override
151df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    public void draw(Canvas canvas) {
15200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        if (mBitmapState.mBitmap != null) {
153935b033edfd9d03129fce6a5b7a1d3a327b74f91susnata            Rect bounds = getBounds();
154935b033edfd9d03129fce6a5b7a1d3a327b74f91susnata            mDest.left = 0;
15500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            mDest.top = mBitmapState.mOffset;
156935b033edfd9d03129fce6a5b7a1d3a327b74f91susnata            mDest.right = bounds.width();
157935b033edfd9d03129fce6a5b7a1d3a327b74f91susnata
158935b033edfd9d03129fce6a5b7a1d3a327b74f91susnata            Rect source = validateSource();
159935b033edfd9d03129fce6a5b7a1d3a327b74f91susnata            float scale = (float) bounds.width() / source.width();
160935b033edfd9d03129fce6a5b7a1d3a327b74f91susnata            mDest.bottom = mDest.top + (int) (source.height() * scale);
161935b033edfd9d03129fce6a5b7a1d3a327b74f91susnata            int i = canvas.save();
162935b033edfd9d03129fce6a5b7a1d3a327b74f91susnata            canvas.clipRect(bounds);
16300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            canvas.drawBitmap(mBitmapState.mBitmap, source, mDest, mBitmapState.mPaint);
164935b033edfd9d03129fce6a5b7a1d3a327b74f91susnata            canvas.restoreToCount(i);
165935b033edfd9d03129fce6a5b7a1d3a327b74f91susnata        }
166df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
167df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
168df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    @Override
169df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    public void setAlpha(int alpha) {
17000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        final int oldAlpha = mBitmapState.mPaint.getAlpha();
171df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata        if (alpha != oldAlpha) {
17200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            mBitmapState.mPaint.setAlpha(alpha);
173df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata            invalidateSelf();
174df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata        }
175df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
176df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
17700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    /**
17800f780c9e3cca0b2e364c61e936147e09877c43fDake Gu     * @return Alpha value between 0(inclusive) and 255(inclusive)
17900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu     */
180e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas    @Override
18100f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    public int getAlpha() {
18200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        return mBitmapState.mPaint.getAlpha();
18300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu    }
18400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu
185df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    @Override
186df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    public void setColorFilter(ColorFilter colorFilter) {
18700f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        mBitmapState.mPaint.setColorFilter(colorFilter);
188df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata        invalidateSelf();
189df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
190df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
191df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    @Override
192df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    public int getOpacity() {
19300f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        final Bitmap bitmap = mBitmapState.mBitmap;
19400f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        return (bitmap == null || bitmap.hasAlpha() || mBitmapState.mPaint.getAlpha() < 255)
19500f780c9e3cca0b2e364c61e936147e09877c43fDake Gu                ? PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE;
196df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
197df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata
198935b033edfd9d03129fce6a5b7a1d3a327b74f91susnata    private Rect validateSource() {
19900f780c9e3cca0b2e364c61e936147e09877c43fDake Gu        if (mBitmapState.mSource == null) {
20000f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            return mBitmapState.mDefaultSource;
201935b033edfd9d03129fce6a5b7a1d3a327b74f91susnata        } else {
20200f780c9e3cca0b2e364c61e936147e09877c43fDake Gu            return mBitmapState.mSource;
203df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata        }
204df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata    }
205e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu
206e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    /**
207e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * Property for {@link #setVerticalOffset(int)} and {@link #getVerticalOffset()}.
208e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     */
209e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    public static final Property<FitWidthBitmapDrawable, Integer> PROPERTY_VERTICAL_OFFSET;
210e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu
211e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    static {
212e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        if (Build.VERSION.SDK_INT >= 24) {
213e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu            // use IntProperty
214e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu            PROPERTY_VERTICAL_OFFSET = getVerticalOffsetIntProperty();
215e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        } else {
216e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu            // use Property
217e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu            PROPERTY_VERTICAL_OFFSET = new Property<FitWidthBitmapDrawable, Integer>(Integer.class,
218e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                    "verticalOffset") {
219e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas                @Override
220e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                public void set(FitWidthBitmapDrawable object, Integer value) {
221e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                    object.setVerticalOffset(value);
222e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                }
223e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu
224e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas                @Override
225e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                public Integer get(FitWidthBitmapDrawable object) {
226e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                    return object.getVerticalOffset();
227e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                }
228e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu            };
229e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        }
230e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    }
231e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu
232c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette    @RequiresApi(24)
233e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    static IntProperty<FitWidthBitmapDrawable> getVerticalOffsetIntProperty() {
234e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        return new IntProperty<FitWidthBitmapDrawable>("verticalOffset") {
235e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas            @Override
236e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu            public void setValue(FitWidthBitmapDrawable fitWidthBitmapDrawable, int value) {
237e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                fitWidthBitmapDrawable.setVerticalOffset(value);
238e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu            }
239e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu
240e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu            @Override
241e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu            public Integer get(FitWidthBitmapDrawable fitWidthBitmapDrawable) {
242e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                return fitWidthBitmapDrawable.getVerticalOffset();
243e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu            }
244e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        };
245e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    }
246df64e524a2bad079e6b0aa2d22c287f2c62aed82susnata}
247