• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.github.mikephil.charting.utils;
2 
3 import android.graphics.Canvas;
4 import android.graphics.LinearGradient;
5 import android.graphics.Paint;
6 import android.graphics.Path;
7 import android.graphics.RectF;
8 import android.graphics.drawable.Drawable;
9 
10 import androidx.annotation.NonNull;
11 import androidx.annotation.Nullable;
12 
13 public class Fill
14 {
15     public enum Type
16     {
17         EMPTY, COLOR, LINEAR_GRADIENT, DRAWABLE
18     }
19 
20     public enum Direction
21     {
22         DOWN, UP, RIGHT, LEFT
23     }
24 
25     /**
26      * the type of fill
27      */
28     private Type mType = Type.EMPTY;
29 
30     /**
31      * the color that is used for filling
32      */
33     @Nullable
34     private Integer mColor = null;
35 
36     private Integer mFinalColor = null;
37 
38     /**
39      * the drawable to be used for filling
40      */
41     @Nullable
42     protected Drawable mDrawable;
43 
44     @Nullable
45     private int[] mGradientColors;
46 
47     @Nullable
48     private float[] mGradientPositions;
49 
50     /**
51      * transparency used for filling
52      */
53     private int mAlpha = 255;
54 
Fill()55     public Fill()
56     {
57     }
58 
Fill(int color)59     public Fill(int color)
60     {
61         this.mType = Type.COLOR;
62         this.mColor = color;
63         calculateFinalColor();
64     }
65 
Fill(int startColor, int endColor)66     public Fill(int startColor, int endColor)
67     {
68         this.mType = Type.LINEAR_GRADIENT;
69         this.mGradientColors = new int[]{startColor, endColor};
70     }
71 
Fill(@onNull int[] gradientColors)72     public Fill(@NonNull int[] gradientColors)
73     {
74         this.mType = Type.LINEAR_GRADIENT;
75         this.mGradientColors = gradientColors;
76     }
77 
Fill(@onNull int[] gradientColors, @NonNull float[] gradientPositions)78     public Fill(@NonNull int[] gradientColors, @NonNull float[] gradientPositions)
79     {
80         this.mType = Type.LINEAR_GRADIENT;
81         this.mGradientColors = gradientColors;
82         this.mGradientPositions = gradientPositions;
83     }
84 
Fill(@onNull Drawable drawable)85     public Fill(@NonNull Drawable drawable)
86     {
87         this.mType = Type.DRAWABLE;
88         this.mDrawable = drawable;
89     }
90 
getType()91     public Type getType()
92     {
93         return mType;
94     }
95 
setType(Type type)96     public void setType(Type type)
97     {
98         this.mType = type;
99     }
100 
101     @Nullable
getColor()102     public Integer getColor()
103     {
104         return mColor;
105     }
106 
setColor(int color)107     public void setColor(int color)
108     {
109         this.mColor = color;
110         calculateFinalColor();
111     }
112 
getGradientColors()113     public int[] getGradientColors()
114     {
115         return mGradientColors;
116     }
117 
setGradientColors(int[] colors)118     public void setGradientColors(int[] colors)
119     {
120         this.mGradientColors = colors;
121     }
122 
getGradientPositions()123     public float[] getGradientPositions()
124     {
125         return mGradientPositions;
126     }
127 
setGradientPositions(float[] positions)128     public void setGradientPositions(float[] positions)
129     {
130         this.mGradientPositions = positions;
131     }
132 
setGradientColors(int startColor, int endColor)133     public void setGradientColors(int startColor, int endColor)
134     {
135         this.mGradientColors = new int[]{startColor, endColor};
136     }
137 
getAlpha()138     public int getAlpha()
139     {
140         return mAlpha;
141     }
142 
setAlpha(int alpha)143     public void setAlpha(int alpha)
144     {
145         this.mAlpha = alpha;
146         calculateFinalColor();
147     }
148 
calculateFinalColor()149     private void calculateFinalColor()
150     {
151         if (mColor == null)
152         {
153             mFinalColor = null;
154         } else
155         {
156             int alpha = (int) Math.floor(((mColor >> 24) / 255.0) * (mAlpha / 255.0) * 255.0);
157             mFinalColor = (alpha << 24) | (mColor & 0xffffff);
158         }
159     }
160 
fillRect(Canvas c, Paint paint, float left, float top, float right, float bottom, Direction gradientDirection)161     public void fillRect(Canvas c, Paint paint,
162                          float left, float top, float right, float bottom,
163                          Direction gradientDirection)
164     {
165         switch (mType)
166         {
167             case EMPTY:
168                 return;
169 
170             case COLOR:
171             {
172                 if (mFinalColor == null) return;
173 
174                 if (isClipPathSupported())
175                 {
176                     int save = c.save();
177 
178                     c.clipRect(left, top, right, bottom);
179                     c.drawColor(mFinalColor);
180 
181                     c.restoreToCount(save);
182                 }
183                 else
184                 {
185                     // save
186                     Paint.Style previous = paint.getStyle();
187                     int previousColor = paint.getColor();
188 
189                     // set
190                     paint.setStyle(Paint.Style.FILL);
191                     paint.setColor(mFinalColor);
192 
193                     c.drawRect(left, top, right, bottom, paint);
194 
195                     // restore
196                     paint.setColor(previousColor);
197                     paint.setStyle(previous);
198                 }
199             }
200             break;
201 
202             case LINEAR_GRADIENT:
203             {
204                 if (mGradientColors == null) return;
205 
206                 LinearGradient gradient = new LinearGradient(
207                         (int) (gradientDirection == Direction.RIGHT
208                                 ? right
209                                 : gradientDirection == Direction.LEFT
210                                 ? left
211                                 : left),
212                         (int) (gradientDirection == Direction.UP
213                                 ? bottom
214                                 : gradientDirection == Direction.DOWN
215                                 ? top
216                                 : top),
217                         (int) (gradientDirection == Direction.RIGHT
218                                 ? left
219                                 : gradientDirection == Direction.LEFT
220                                 ? right
221                                 : left),
222                         (int) (gradientDirection == Direction.UP
223                                 ? top
224                                 : gradientDirection == Direction.DOWN
225                                 ? bottom
226                                 : top),
227                         mGradientColors,
228                         mGradientPositions,
229                         android.graphics.Shader.TileMode.MIRROR);
230 
231                 paint.setShader(gradient);
232 
233                 c.drawRect(left, top, right, bottom, paint);
234             }
235             break;
236 
237             case DRAWABLE:
238             {
239                 if (mDrawable == null) return;
240 
241                 mDrawable.setBounds((int) left, (int) top, (int) right, (int) bottom);
242                 mDrawable.draw(c);
243             }
244             break;
245         }
246     }
247 
fillPath(Canvas c, Path path, Paint paint, @Nullable RectF clipRect)248     public void fillPath(Canvas c, Path path, Paint paint,
249                          @Nullable RectF clipRect)
250     {
251         switch (mType)
252         {
253             case EMPTY:
254                 return;
255 
256             case COLOR:
257             {
258                 if (mFinalColor == null) return;
259 
260                 if (clipRect != null && isClipPathSupported())
261                 {
262                     int save = c.save();
263 
264                     c.clipPath(path);
265                     c.drawColor(mFinalColor);
266 
267                     c.restoreToCount(save);
268                 }
269                 else
270                 {
271                     // save
272                     Paint.Style previous = paint.getStyle();
273                     int previousColor = paint.getColor();
274 
275                     // set
276                     paint.setStyle(Paint.Style.FILL);
277                     paint.setColor(mFinalColor);
278 
279                     c.drawPath(path, paint);
280 
281                     // restore
282                     paint.setColor(previousColor);
283                     paint.setStyle(previous);
284                 }
285             }
286             break;
287 
288             case LINEAR_GRADIENT:
289             {
290                 if (mGradientColors == null) return;
291 
292                 LinearGradient gradient = new LinearGradient(
293                         0,
294                         0,
295                         c.getWidth(),
296                         c.getHeight(),
297                         mGradientColors,
298                         mGradientPositions,
299                         android.graphics.Shader.TileMode.MIRROR);
300 
301                 paint.setShader(gradient);
302 
303                 c.drawPath(path, paint);
304             }
305             break;
306 
307             case DRAWABLE:
308             {
309                 if (mDrawable == null) return;
310 
311                 ensureClipPathSupported();
312 
313                 int save = c.save();
314                 c.clipPath(path);
315 
316                 mDrawable.setBounds(
317                         clipRect == null ? 0 : (int) clipRect.left,
318                         clipRect == null ? 0 : (int) clipRect.top,
319                         clipRect == null ? c.getWidth() : (int) clipRect.right,
320                         clipRect == null ? c.getHeight() : (int) clipRect.bottom);
321                 mDrawable.draw(c);
322 
323                 c.restoreToCount(save);
324             }
325             break;
326         }
327     }
328 
isClipPathSupported()329     private boolean isClipPathSupported()
330     {
331         return Utils.getSDKInt() >= 18;
332     }
333 
ensureClipPathSupported()334     private void ensureClipPathSupported()
335     {
336         if (Utils.getSDKInt() < 18)
337         {
338             throw new RuntimeException("Fill-drawables not (yet) supported below API level 18, " +
339                     "this code was run on API level " + Utils.getSDKInt() + ".");
340         }
341     }
342 }
343