From e8b90f67885d33685ba4a7a0c6ac82dc70b977f5 Mon Sep 17 00:00:00 2001
From: Jakob Grabner <285173036@qq.com>
Date: Thu, 13 Aug 2015 21:56:24 +0200
Subject: [PATCH] Edit: Calling setupPaints() after setting a color is no
longer necessary. Added: Bitmap clipping support. Added: Documentation.
---
.../circleprogress/CircleProgressView.java | 303 +++++++++++++-----
.../src/main/res/values/attrs.xml | 28 +-
.../at/grabner/circleview/MainActivity.java | 28 +-
ExampleApp/src/main/res/drawable/mask.png | Bin 0 -> 18102 bytes
aar/CircleProgressView.aar | Bin 17350 -> 18323 bytes
5 files changed, 274 insertions(+), 85 deletions(-)
create mode 100644 ExampleApp/src/main/res/drawable/mask.png
diff --git a/CircleProgressView/src/main/java/at/grabner/circleprogress/CircleProgressView.java b/CircleProgressView/src/main/java/at/grabner/circleprogress/CircleProgressView.java
index 39ffed4..8365d0f 100644
--- a/CircleProgressView/src/main/java/at/grabner/circleprogress/CircleProgressView.java
+++ b/CircleProgressView/src/main/java/at/grabner/circleprogress/CircleProgressView.java
@@ -3,11 +3,14 @@
import android.animation.TimeInterpolator;
import android.content.Context;
import android.content.res.TypedArray;
+import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
@@ -83,7 +86,7 @@ public class CircleProgressView extends View {
private final int mBarColorStandard = 0xff009688; //stylish blue
private int mContourColor = 0xAA000000;
private int mSpinnerColor = mBarColorStandard; //stylish blue
- private int mFillColor = 0x00000000; //transparent
+ private int mBackgroundCircleColor = 0x00000000; //transparent
private int mRimColor = 0xAA83d0c9;
private int mTextColor = 0xFF000000;
private int mUnitColor = 0xFF000000;
@@ -97,15 +100,16 @@ public class CircleProgressView extends View {
//Paints
private Paint mBarPaint = new Paint();
private Paint mBarSpinnerPaint = new Paint();
- private Paint mCirclePaint = new Paint();
+ private Paint mBackgroundCirclePaint = new Paint();
private Paint mRimPaint = new Paint();
private Paint mTextPaint = new Paint();
private Paint mUnitTextPaint = new Paint();
private Paint mContourPaint = new Paint();
//Rectangles
private RectF mCircleBounds = new RectF();
- private RectF mInnerCircleBounds = new RectF();
- private RectF mTextBounds = new RectF();
+ private RectF mInnerCircleBound = new RectF();
+ private RectF mOuterTextBounds = new RectF();
+ private RectF mActualTextBounds = new RectF();
private RectF mUnitBounds = new RectF();
private RectF mCircleOuterContour = new RectF();
private RectF mCircleInnerContour = new RectF();
@@ -146,6 +150,12 @@ public class CircleProgressView extends View {
private boolean mShowUnit = false;
+
+
+ //clipping
+ private Bitmap mClippingBitmap;
+ private Paint mMaskPaint;
+
/**
* Relative size of the unite string to the value string.
*/
@@ -154,6 +164,10 @@ public class CircleProgressView extends View {
+
+
+
+
//endregion members
/**
@@ -167,6 +181,10 @@ public CircleProgressView(Context context, AttributeSet attrs) {
parseAttributes(context.obtainStyledAttributes(attrs,
R.styleable.CircleProgressView));
+
+ mMaskPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mMaskPaint.setFilterBitmap(false);
+ mMaskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
}
/**
@@ -221,8 +239,8 @@ private void parseAttributes(TypedArray a) {
setRimColor(a.getColor(R.styleable.CircleProgressView_rimColor,
mRimColor));
- setFillColor(a.getColor(R.styleable.CircleProgressView_fillColor,
- mFillColor));
+ setBackgroundCircleColor(a.getColor(R.styleable.CircleProgressView_fillColor,
+ mBackgroundCircleColor));
setContourColor(a.getColor(R.styleable.CircleProgressView_contourColor, mContourColor));
setContourSize(a.getDimension(R.styleable.CircleProgressView_contourSize, mContourSize));
@@ -308,7 +326,7 @@ private RectF getInnerCircleRect(RectF _circleBounds) {
private float calcTextSizeForCircle(String _text, Paint _textPaint, RectF _circleBounds) {
- //get mTextBounds bounds
+ //get mActualTextBounds bounds
RectF innerCircleBounds = getInnerCircleRect(_circleBounds);
return calcTextSizeForRect(_text, _textPaint, innerCircleBounds);
@@ -346,17 +364,33 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mLayoutHeight = h;
setupBounds();
- setupPaints();
+ setupBarPaint();
+
+ if (mClippingBitmap != null) {
+ mClippingBitmap = Bitmap.createScaledBitmap(mClippingBitmap, getWidth(), getHeight(), false);
+ }
+
invalidate();
}
//region setter / getter
+ /**
+ *
+ * @param _relativeUniteSize The relative size (scale factor) of the unit text size to the text size.
+ * Especially useful for autotextsize=true;
+ */
+ public void setRelativeUniteSize(float _relativeUniteSize) {
+ mRelativeUniteSize = _relativeUniteSize;
+ }
public Paint.Cap getSpinnerStrokeCap() {
return mSpinnerStrokeCap;
}
+ /**
+ * @param _spinnerStrokeCap The stroke cap of the progress bar in spinning mode.
+ */
public void setSpinnerStrokeCap(Paint.Cap _spinnerStrokeCap) {
mSpinnerStrokeCap = _spinnerStrokeCap;
}
@@ -365,6 +399,10 @@ public Paint.Cap getBarStrokeCap() {
return mBarStrokeCap;
}
+ /**
+ *
+ * @param _barStrokeCap The stroke cap of the progress bar.
+ */
public void setBarStrokeCap(Paint.Cap _barStrokeCap) {
mBarStrokeCap = _barStrokeCap;
}
@@ -373,23 +411,32 @@ public int getContourColor() {
return mContourColor;
}
+ /**
+ *
+ * @param _contourColor The color of the background contour of the circle.
+ */
public void setContourColor(int _contourColor) {
mContourColor = _contourColor;
+ setupContourPaint();
}
public float getContourSize() {
return mContourSize;
}
+ /**
+ *
+ * @param _contourSize The size of the background contour of the circle.
+ */
public void setContourSize(float _contourSize) {
mContourSize = _contourSize;
}
/**
* Set the text in the mCurrentValue bar. If no text (null or empty) is specified,
- * * the current percentage value is used
- * * (max value and current value are mandatory to do so).
- * *
+ * the current percentage value is used
+ * max value and current value are mandatory to do so).
+ * @param text The text to show
*/
public void setText(String text) {
if (text == null || text.isEmpty()) {
@@ -406,6 +453,11 @@ public String getUnit() {
return mUnit;
}
+ /**
+ *
+ * @param _unit The unit to show next to the current value.
+ * You also need to set {@link #setShowUnit(boolean)} to true.
+ */
public void setUnit(String _unit) {
if (_unit == null) {
mUnit = "";
@@ -447,7 +499,7 @@ public boolean isShowPercentAsAutoValue() {
/**
* If true and no text was specified. The percentage (max value, current value) is shown.
- * If false the current value is shown.
+ * If false the current value is shown. If a text was specified the text is shown.
* @param _showPercentAsAutoValue bool
*/
public void setShowPercentAsAutoValue(boolean _showPercentAsAutoValue) {
@@ -460,7 +512,7 @@ public int getTextSize() {
/**
* If text size was not set, it is automatically calculated
- * @param textSize The text size or 0 enable automatic size (default)
+ * @param textSize The text size or 0 to enable automatic size (default)
*/
public void setTextSize(int textSize) {
if (textSize > 0) {
@@ -475,6 +527,11 @@ public double getMaxValue() {
return mMaxValue;
}
+ /**
+ * The max value of the progress bar. Used to calculate the percentage of the current value.
+ * The bar fills according to the percentage. The default value is 100.
+ * @param _maxValue The max value.
+ */
public void setMaxValue(float _maxValue) {
mMaxValue = _maxValue;
}
@@ -519,11 +576,15 @@ public boolean isShowUnit() {
return mShowUnit;
}
+ /**
+ *
+ * @param _showUnit True to show unite, flas to hide.
+ */
public void setShowUnit(boolean _showUnit) {
mShowUnit = _showUnit;
mTextLength = 0; // triggers recalculating text sizes
invalidate();
- mInnerCircleBounds = getInnerCircleRect(mCircleBounds);
+ mOuterTextBounds = getInnerCircleRect(mCircleBounds);
}
@@ -570,6 +631,10 @@ public int getBarWidth() {
return mBarWidth;
}
+ /**
+ *
+ * @param barWidth The width of the progress bar in pixel.
+ */
public void setBarWidth(int barWidth) {
this.mBarWidth = barWidth;
}
@@ -578,33 +643,54 @@ public int[] getBarColors() {
return mBarColors;
}
+
+ /**
+ *Sets the color of progress bar.
+ * @param barColors One or more colors. If more than one color is specified, a gradient of the colors is used.
+ *
+ */
public void setBarColor(int... barColors) {
if (barColors.length == 1) {
this.mBarColors = new int[]{barColors[0], barColors[0]};
} else {
this.mBarColors = barColors;
}
-
+ setupBarPaint();
}
+ /**
+ *
+ * @param _color The color of progress the bar in spinning mode.
+ */
public void setSpinBarColor(int _color) {
mSpinnerColor = _color;
+ setupBarSpinnerPaint();
}
- public int getFillColor() {
- return mFillColor;
+ public int getBackgroundCircleColor() {
+ return mBackgroundCircleColor;
}
- public void setFillColor(int circleColor) {
- this.mFillColor = circleColor;
+ /**
+ * Sets the background color of the entire Progress Circle.
+ * @param circleColor the color.
+ */
+ public void setBackgroundCircleColor(int circleColor) {
+ this.mBackgroundCircleColor = circleColor;
+ setupBackgroundCirclePaint();
}
public int getRimColor() {
return mRimColor;
}
+ /**
+ *
+ * @param rimColor The color of the rim around the Circle.
+ */
public void setRimColor(int rimColor) {
this.mRimColor = rimColor;
+ setupRimPaint();
}
public Shader getRimShader() {
@@ -629,14 +715,20 @@ public int getTextColor() {
/**
* *
- * @param textColor the color or -1 to use auto color (depending on bar colors)
+ * @param textColor the color or -1 to use auto color (depending on bar colors and current value)
*/
public void setTextColor(int textColor) {
this.mTextColor = textColor;
+ setupTextPaint();
}
- public void setUnitColor(int textColor) {
- this.mUnitColor = textColor;
+ /**
+ * the color or -1 to use auto color (depending on bar colors and current value)
+ * @param unitColor The color.
+ */
+ public void setUnitColor(int unitColor) {
+ this.mUnitColor = unitColor;
+ setupUnitTextPaint();
}
public float getSpinSpeed() {
@@ -644,7 +736,7 @@ public float getSpinSpeed() {
}
/**
- * The amount of degree to move the bar by on each draw
+ * The amount of degree to move the bar on every draw call.
* @param spinSpeed the speed of the spinner
*/
public void setSpinSpeed(float spinSpeed) {
@@ -655,31 +747,110 @@ public int getRimWidth() {
return mRimWidth;
}
+ /**
+ *
+ * @param rimWidth The width in pixel of the rim around the circle
+ */
public void setRimWidth(int rimWidth) {
this.mRimWidth = rimWidth;
}
+ /**
+ *
+ * @return The number of ms to wait between each draw call.
+ */
public int getDelayMillis() {
return mDelayMillis;
}
+ /**
+ *
+ * @param delayMillis The number of ms to wait between each draw call.
+ */
public void setDelayMillis(int delayMillis) {
this.mDelayMillis = delayMillis;
}
+ /**
+ * @param _clippingBitmap The bitmap used for clipping. Set to null to disable clipping.
+ * Default: No clipping.
+ */
+ public void setClippingBitmap(Bitmap _clippingBitmap) {
+
+ if(getWidth() > 0 && getHeight() > 0){
+ mClippingBitmap = Bitmap.createScaledBitmap(_clippingBitmap, getWidth(), getHeight(), false);
+ }else{
+ mClippingBitmap = _clippingBitmap;
+ }
+ if (mClippingBitmap == null) {
+ // enable HW acceleration
+ setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ }else{
+ // disable HW acceleration
+ setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+ }
+ }
+
+
+ /**
+ *
+ * @return The relative size (scale factor) of the unit text size to the text size
+ */
+ public float getRelativeUniteSize() {
+ return mRelativeUniteSize;
+ }
+
//endregion getter / setter
//----------------------------------
//region Setting up stuff
//----------------------------------
- /**
- * Set the properties of the paints we're using to
- * draw all the things.
- *
- * Call this if you change colors after the view was drawn
- */
- public void setupPaints() {
+
+
+ private void setupContourPaint() {
+ mContourPaint.setColor(mContourColor);
+ mContourPaint.setAntiAlias(true);
+ mContourPaint.setStyle(Style.STROKE);
+ mContourPaint.setStrokeWidth(mContourSize);
+ }
+
+ private void setupUnitTextPaint() {
+ mUnitTextPaint.setColor(mUnitColor);
+ mUnitTextPaint.setStyle(Style.FILL);
+ mUnitTextPaint.setAntiAlias(true);
+ mUnitTextPaint.setTextSize(getTextSize());
+ }
+
+ private void setupTextPaint() {
+ mTextPaint.setColor(mTextColor);
+ mTextPaint.setStyle(Style.FILL);
+ mTextPaint.setAntiAlias(true);
+ mTextPaint.setTextSize(getTextSize());
+ }
+
+ private void setupBackgroundCirclePaint() {
+ mBackgroundCirclePaint.setColor(mBackgroundCircleColor);
+ mBackgroundCirclePaint.setAntiAlias(true);
+ mBackgroundCirclePaint.setStyle(Style.FILL);
+ }
+
+ private void setupRimPaint() {
+ mRimPaint.setColor(mRimColor);
+ mRimPaint.setAntiAlias(true);
+ mRimPaint.setStyle(Style.STROKE);
+ mRimPaint.setStrokeWidth(mRimWidth);
+ }
+
+ private void setupBarSpinnerPaint() {
+ mBarSpinnerPaint.setAntiAlias(true);
+ mBarSpinnerPaint.setStrokeCap(mSpinnerStrokeCap);
+ mBarSpinnerPaint.setStyle(Style.STROKE);
+ mBarSpinnerPaint.setStrokeWidth(mBarWidth);
+ mBarSpinnerPaint.setColor(mSpinnerColor);
+ }
+
+ private void setupBarPaint() {
mBarPaint.setShader(new SweepGradient(mCircleBounds.centerX(), mCircleBounds.centerY(), mBarColors, null));
Matrix matrix = new Matrix();
mBarPaint.getShader().getLocalMatrix(matrix);
@@ -694,36 +865,6 @@ public void setupPaints() {
mBarPaint.setStrokeCap(mBarStrokeCap);
mBarPaint.setStyle(Style.STROKE);
mBarPaint.setStrokeWidth(mBarWidth);
-
- mBarSpinnerPaint.setAntiAlias(true);
- mBarSpinnerPaint.setStrokeCap(mSpinnerStrokeCap);
- mBarSpinnerPaint.setStyle(Style.STROKE);
- mBarSpinnerPaint.setStrokeWidth(mBarWidth);
- mBarSpinnerPaint.setColor(mSpinnerColor);
-
- mRimPaint.setColor(mRimColor);
- mRimPaint.setAntiAlias(true);
- mRimPaint.setStyle(Style.STROKE);
- mRimPaint.setStrokeWidth(mRimWidth);
-
- mCirclePaint.setColor(mFillColor);
- mCirclePaint.setAntiAlias(true);
- mCirclePaint.setStyle(Style.FILL);
-
- mTextPaint.setColor(mTextColor);
- mTextPaint.setStyle(Style.FILL);
- mTextPaint.setAntiAlias(true);
- mTextPaint.setTextSize(getTextSize());
-
- mUnitTextPaint.setColor(mUnitColor);
- mUnitTextPaint.setStyle(Style.FILL);
- mUnitTextPaint.setAntiAlias(true);
- mUnitTextPaint.setTextSize(getTextSize());
-
- mContourPaint.setColor(mContourColor);
- mContourPaint.setAntiAlias(true);
- mContourPaint.setStyle(Style.STROKE);
- mContourPaint.setStrokeWidth(mContourSize);
}
/**
@@ -751,7 +892,11 @@ private void setupBounds() {
mPaddingTop + mBarWidth,
width - mPaddingRight - mBarWidth,
height - mPaddingBottom - mBarWidth);
- mInnerCircleBounds = getInnerCircleRect(mCircleBounds);
+ mInnerCircleBound = new RectF(mPaddingLeft + (mBarWidth * 1.5f),
+ mPaddingTop + (mBarWidth * 1.5f),
+ width - mPaddingRight - (mBarWidth * 1.5f),
+ height - mPaddingBottom - (mBarWidth * 1.5f));
+ mOuterTextBounds = getInnerCircleRect(mCircleBounds);
mCircleInnerContour = new RectF(mCircleBounds.left + (mRimWidth / 2.0f) + (mContourSize / 2.0f), mCircleBounds.top + (mRimWidth / 2.0f) + (mContourSize / 2.0f), mCircleBounds.right - (mRimWidth / 2.0f) - (mContourSize / 2.0f), mCircleBounds.bottom - (mRimWidth / 2.0f) - (mContourSize / 2.0f));
mCircleOuterContour = new RectF(mCircleBounds.left - (mRimWidth / 2.0f) - (mContourSize / 2.0f), mCircleBounds.top - (mRimWidth / 2.0f) - (mContourSize / 2.0f), mCircleBounds.right + (mRimWidth / 2.0f) + (mContourSize / 2.0f), mCircleBounds.bottom + (mRimWidth / 2.0f) + (mContourSize / 2.0f));
@@ -765,6 +910,7 @@ private void setupBounds() {
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
+
if (DEBUG) {
drawDebug(canvas);
@@ -772,8 +918,8 @@ protected void onDraw(Canvas canvas) {
float degrees = (360f / mMaxValue * mCurrentValue);
- //Draw the inner circle
- canvas.drawArc(mCircleBounds, 360, 360, false, mCirclePaint);
+ //Draw the background circle
+ canvas.drawArc(mInnerCircleBound, 360, 360, false, mBackgroundCirclePaint);
//Draw the rim
if(mRimWidth > 0){
canvas.drawArc(mCircleBounds, 360, 360, false, mRimPaint);
@@ -802,6 +948,11 @@ protected void onDraw(Canvas canvas) {
drawCircleWithNumber(canvas, degrees);
}
+
+ if (mClippingBitmap != null) {
+ canvas.drawBitmap(mClippingBitmap, 0, 0, mMaskPaint);
+ }
+
}
private void drawSpinningArc(Canvas canvas) {
@@ -820,7 +971,7 @@ private void drawDebug(Canvas canvas){
canvas.drawRect(mCircleBounds, innerRectPaint);
innerRectPaint.setColor(Color.MAGENTA);
- canvas.drawRect(mInnerCircleBounds, innerRectPaint);
+ canvas.drawRect(mOuterTextBounds, innerRectPaint);
}
private void drawCircleWithNumber(Canvas canvas, float _degrees) {
@@ -856,33 +1007,33 @@ private void drawCircleWithNumber(Canvas canvas, float _degrees) {
update = true;
mTextLength = text.length();
if (mTextLength == 1) {
- mInnerCircleBounds = new RectF(mInnerCircleBounds.left + (mInnerCircleBounds.width() * 0.1f), mInnerCircleBounds.top, mInnerCircleBounds.right - (mInnerCircleBounds.width() * 0.1f), mInnerCircleBounds.bottom);
+ mOuterTextBounds = new RectF(mOuterTextBounds.left + (mOuterTextBounds.width() * 0.1f), mOuterTextBounds.top, mOuterTextBounds.right - (mOuterTextBounds.width() * 0.1f), mOuterTextBounds.bottom);
}else {
- mInnerCircleBounds = getInnerCircleRect(mCircleBounds);
+ mOuterTextBounds = getInnerCircleRect(mCircleBounds);
}
- RectF textRect = mInnerCircleBounds;
+ RectF textRect = mOuterTextBounds;
if (mShowUnit) {
//shrink text Rect so that there is space for the unit
- textRect = new RectF(mInnerCircleBounds.left, mInnerCircleBounds.top, mInnerCircleBounds.right - ((mInnerCircleBounds.width() * (mRelativeUniteSize))*relativeGap), mInnerCircleBounds.bottom);
+ textRect = new RectF(mOuterTextBounds.left, mOuterTextBounds.top, mOuterTextBounds.right - ((mOuterTextBounds.width() * (mRelativeUniteSize))*relativeGap), mOuterTextBounds.bottom);
}
mTextPaint.setTextSize(calcTextSizeForRect(text, mTextPaint, textRect)* mTextScale);
- mTextBounds = getTextBounds(text, mTextPaint, textRect); // center text in text rect
+ mActualTextBounds = getTextBounds(text, mTextPaint, textRect); // center text in text rect
}
} else {
- mTextBounds = getTextBounds(text, mTextPaint, mCircleBounds); //center text in circle
+ mActualTextBounds = getTextBounds(text, mTextPaint, mCircleBounds); //center text in circle
}
if (DEBUG){
Paint rectPaint = new Paint();
rectPaint.setColor(Color.GREEN);
- canvas.drawRect(mTextBounds, rectPaint);
+ canvas.drawRect(mActualTextBounds, rectPaint);
}
- canvas.drawText(text, mTextBounds.left-(mTextPaint.getTextSize()*0.09f), mTextBounds.bottom, mTextPaint);
+ canvas.drawText(text, mActualTextBounds.left-(mTextPaint.getTextSize()*0.09f), mActualTextBounds.bottom, mTextPaint);
if (mShowUnit) {
@@ -894,11 +1045,11 @@ private void drawCircleWithNumber(Canvas canvas, float _degrees) {
}
if (update) {
//calc unit text position
- mUnitBounds = new RectF(mInnerCircleBounds.left + (mInnerCircleBounds.width() * (1 - mRelativeUniteSize) * relativeGap), mInnerCircleBounds.top, mInnerCircleBounds.right, mInnerCircleBounds.bottom);
+ mUnitBounds = new RectF(mOuterTextBounds.left + (mOuterTextBounds.width() * (1 - mRelativeUniteSize) * relativeGap), mOuterTextBounds.top, mOuterTextBounds.right, mOuterTextBounds.bottom);
mUnitTextPaint.setTextSize(calcTextSizeForRect(mUnit, mUnitTextPaint, mUnitBounds) * mUnitScale);
mUnitBounds = getTextBounds(mUnit, mUnitTextPaint, mUnitBounds);
//move unite to top of text
- float dy = mTextBounds.top - mUnitBounds.top;
+ float dy = mActualTextBounds.top - mUnitBounds.top;
mUnitBounds.offset(0, dy);
}
@@ -918,14 +1069,14 @@ private void drawCircleWithNumber(Canvas canvas, float _degrees) {
//region important getter / setter
//----------------------------------
/**
- * Turn off spin mode
+ * Turn off spinning mode
*/
public void stopSpinning() {
mAnimationHandler.sendEmptyMessage(AnimationMsg.STOP_SPINNING.ordinal());
}
/**
- * Puts the view on spin mode
+ * Puts the view in spin mode
*/
public void spin() {
mAnimationHandler.sendEmptyMessage(AnimationMsg.START_SPINNING.ordinal());
diff --git a/CircleProgressView/src/main/res/values/attrs.xml b/CircleProgressView/src/main/res/values/attrs.xml
index 5081264..8a43e04 100644
--- a/CircleProgressView/src/main/res/values/attrs.xml
+++ b/CircleProgressView/src/main/res/values/attrs.xml
@@ -1,27 +1,39 @@
+
-
+
-
+
+
+
+
+
-
-
-
+
+
+
-
+
+
+
+
+
+
-
-
+
+
+
+
\ No newline at end of file
diff --git a/ExampleApp/src/main/java/at/grabner/circleview/MainActivity.java b/ExampleApp/src/main/java/at/grabner/circleview/MainActivity.java
index 82f53c4..eb1b40e 100644
--- a/ExampleApp/src/main/java/at/grabner/circleview/MainActivity.java
+++ b/ExampleApp/src/main/java/at/grabner/circleview/MainActivity.java
@@ -1,5 +1,9 @@
package at.grabner.circleview;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
@@ -75,7 +79,7 @@ public void onStartTrackingTouch(SeekBar seekBar) {
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
- mCircleView.setValueAnimated(seekBar.getProgress(),1500);
+ mCircleView.setValueAnimated(seekBar.getProgress(), 1500);
mSwitchSpin.setChecked(false);
}
});
@@ -100,6 +104,9 @@ public void onStopTrackingTouch(SeekBar seekBar) {
});
+
+ mCircleView.setBackgroundCircleColor(Color.RED);
+
}
@@ -131,5 +138,24 @@ protected void onStart() {
mCircleView.setValue(0);
mCircleView.setValueAnimated(42);
}
+
+ public static Bitmap getMaskingBitmap(Resources res, int sourceResId) {
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ options.inMutable = true;
+ }
+ options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+ Bitmap source = BitmapFactory.decodeResource(res, sourceResId, options);
+ Bitmap bitmap;
+ if (source.isMutable()) {
+ bitmap = source;
+ } else {
+ bitmap = source.copy(Bitmap.Config.ARGB_8888, true);
+ source.recycle();
+ }
+ bitmap.setHasAlpha(true);
+
+ return bitmap;
+ }
}
diff --git a/ExampleApp/src/main/res/drawable/mask.png b/ExampleApp/src/main/res/drawable/mask.png
new file mode 100644
index 0000000000000000000000000000000000000000..8a527408fd03fa3e20cad86abe849484a7423bc7
GIT binary patch
literal 18102
zcmeI3c{r5o|HmJ3?4(61>5L^wX0r@4jj@b1TNoMbW9FGLS!S3iODBg)w0x74HIC}Y
zuA-DsNGKsXT2Lw^b?AGjqf_Dg427OF=UmtK`}^Z}T{G7;%jfgC-=F)wU-##}=b5>#
z=fFB=TLsyrvH$=m*xOmTLGSf~r?e#WT0kvKhu&nkc3wOHKxqn|Vj-DkI{`q}g-s@}
zTj#^!b9g=+F2bHnMsR~TOtv2g03q#Z?ktLX|02_oCvPnsVj_+^aNLxo5pI@;A{NGJ
z>#EBrt&LGX^+?&ZYM!;Vglc_8jQEiw5r>ss_2duAK9uTFKYe8HnV5sOKR(-a#`k{t
z$cx6YOAknW`NL_&%~F-p@(FeZu0|2^IhM=kJ>6SZQ~Rt3WgaQ3#RZh4iy7*?QB5)6
zeK?W0TBB0x8Xy*OPfi-BbV{wnEQ=nW`^qwTlUT$)u}XfNiGy^+Lcl!ih~-(p+(s-S
zElJxQ$dCZGHPF4gfpth=+sdC`+yf%g-Y4%812!I4R~E~N0}uv2AWT2F%Cu+G)lfBC7g*e(AT8cTUIy8BSex%{tr^9yuAR|s0
zn(gptNRwh=Qxon;iQ-n|tLu{E8s6UBW4+CJTyp?;#t&~9(?b_8jaVZY;XihI#h`@G
z7P*WaBZrtpbImUS8U5{^!(0Iy>r+QdA3f^r>3O)e#&RR=w&(6KR`u3O&r!d>!ik?o
z-aWncTq{z4bEK`r`=`}+-a2M3Yd$8k&%5(QtnH`Ea^s)W?rGH6dzVsm7k0bO4?JR(
za(GxjQ{#Z;u~j!$w2m{LcjepD=ie|cClHVGyqs-MCzWmP<>mqSg%rYS=A4n
zRdS!U;r3Z-)l^$5S;{gZmIZBFmA}VQXMf{)HQjCK-^|qvD_wo|$8!}?)gD(AO}TSF
z(4^C=bjl-TBrNKs7tqw(W5m1wU@ntDKg&!_$6w%Fs5MXsj5$zLLuW*aZvXLDNaE`yIviCvVDdN=6e
zQq#k@Q+;>yeCD>tlE`(K%9o3!3~Kx^sM;Hr7fkeI;^_?+H1g&1YL}j0pD$i^;2pjB
zLa@aANb5=&oJ6oCg0|ekj_OEterT7CSf*t-uU*DiMtq-Z^-7KSY=?{5SLgjzv)Ef7
z8%?#-)4V@Fb^%&xR}8tvSZn?Pvi{1_qjT&p{7Pw^-)hqu;HKHHmy>E}w^TF!Ry)JD
zND6;k53#yFswb`IMvp;{YLEKRM%grP^T1!{FC^MzI?#3r>}|opX)OUSPN*1>d-Lk-bA^!RZtCminmpjIhtW}_(EOr|{&NP$iP6~W~lJ6|jr<0X99DeZ0!Z)j)uTnj0
z=vaycH~Ho!BqmVv?DAamY+qO43J0>%&Q@5Ld3}sjw5VIVa??s%R&3J`X?^aG+#hGj
zW-W3uCA=#{<@#o-o+`5nz8;V@n3R5POGLUOC+kUQMc;>IyV0YRQU4EF?`-9%lEv~`
zk{$9*i-|Xl0y#uAbX~_EuH?-(%*mOw6STx<`{GJlh-cbt{$(@wFuQhBw^p}*t$*zq
zZAoo)Z3m}UPJ=0KPNip8on7O<8yPPUGpu`^iSBrq~DieW`t^4^q1>Z`%;EL9Zmc
zeC!{%a}g0zAa_sa^(vgT!#I>$TbrQc`WIR8hGB;V-Mwy$pDFZ`6~Yy7so1$^CKy4&4ZsUl|o0<+o;>lPc>D)jmlb-gPN~LNHBMdaW*;rZwn>e>_vxH3@r#=aYQz>
zTCJL;fo{RI#5^Q#(p~O6WT)#CcI@}Ka-&eKn+BPBy`}qB<{T||RB(KpN=RRnvJ>I2
zZ%U}Z?mZTFG|)0v-6_6=^@{a^xw9c3j4B$t8F1(_die>dTfW6d^MCL{%9dE3eM#A%
z^FUXshy{8wuQwjJjZer+U)?xxr}%cqQR9Whl}?f4>M
zU}%SIxAG6G_pg`CCtf*NqU+!0k~iR)SQuWR9p>a4xuxp%o~lb?zOUsxWP77_zwUf6
zu-S!*_UgJs`>;Pvm85*&VBx|Jl|<#AAL?|5^r}X4ZeLICJbp1JucnmI%xq=$zj%U7
z->8_7oA@G8F+kx_`$dJW^%n=;{b}8SPHfcaDBD{?EZ7y4BRU#*FeS!dCxR{8z-W__I(X5@W
zGIn~bp-^QJI{bax>jzCONiC-mhZ5tj`~Q?V`l|Bvl5-uk)wRp7-3l?lZh5=@<3Lq#
zXRz9vGhK6CdVWIutTXQO*M)cPce6gmFNu#Imk>`H{zNxGb^rij1)D3D{Q8A+BHLVyzZgM1ny#NRJ~M+h<1n8-_jJ`3Dv4a7tfzOSiotjPWR}k+HF%u^vJngEc~94A2G`q`m>c5JNE3M|^&0kYu4x#2^Nf
z;AUm>xjV=*)$rl-xdb#iI5-#;Y=GhfvCvpN9*@T8qxJQXPzxk4G=NVFK?d+NCzE{1
zV+Hc)L2NFc%?UsV^3uFHJNTv=8iJ0d9-rss&z1aj%FnL
zrX!aiHgp`({ARQf%!MJC3!Z6!Gx0V;(r_RHNy8iBktP@>9Z6^4Kx0ED)0=KGxm3_x
zW=Zo+S9WY3R79aOiVG^Si37(S4E);rCE&-NI5@bpARZ{#kER-5HssVvGj)&%G!y%p
zK%)ze91>knwIG9t{>nQ&tSRMZ8GDxH{6`2T^UsifzmH%aFyOmYKbdEu$@eqxI81&p
zEeNz=LFMsJcH?B$uVwJ`M6}?1_GAAatOAd=^S@k!f3&6k|F6Mx{nCAC0W6R~LVqdU
zFOGkwL1!2asgJ_WOf#e1j68yGHNiOpl|5}@e?yvY
zeDL;E!Fl1gW3oNg1dD~PTCf=C@mV`F4%d49jdo@nuAP>81hDx6N)tncxo4;ZU%rG1
ztnSctB1nQJ2Y10+uVaURepD+q^gY27oOk+ySxt!Gky({q-&M|td{$1D)Qs!7iGyO&
z3tcTj7pmx~E7fn#kg0R_fB9j0O8?8Ouw0@}U_gYMB3#1xz@j2tFd)KB5ia3;U{Mh+
z7!cv62$yg^u&4+Z42W=3giAOdSX6`y21K|i!X=y!EGohU10viM;S$aV78T)w0TFJB
za0%xFi;8f;fCx85xPmvBC?
zs0bGfh;UPcOE@1`RD=r#M7Sx!C7cf|D#8T=BHR?=63zz}72$#b5pIfb3FiZgig3Yz
z2scHzg!6$#MYv!&Z&OzU5b_chYd?%jJ&3SItkz|wb8o#ko!d0$T8WG~0->ZN
zEiEB2XO388gt<9F@ccU$Fwyd>R?{x|1Z|%M+W&@N6Dg@3OZQHi7OaJ-%_KVy1^m`rA{a!}oipW@V&apBw
z$NKV{F>@$LgMz^T0YO0l0V?6ef&OYBK>ujae|1?=WkFg=IWc-re;|c_F|79kxyJd+
z0PC-g`X3Et1?42gM3t23WW^q2Cnsd2Y3b(RrD>_ACubTI85Ws$kM@s1{zEXh7w~(ZJBw#PL7NCiaeYW{xIKPXEa>UeL)r
z02l~J2VauoH;_2=xWxLp8K6SnP7Z>e`w7Fk9&GYkh~^rRGbD
z>k|YH1;<5poKp31m&_vwN*3DEdO1{ZKy9-e$N0hDL#P+^vj&PSA)l+BfSfJj=%eQXv{A?8{T(EXvW~P&)^y_dP
zDu1c`Q{s)5jlz^0Ya`T*EJJEArPysf;~QIyA67?kKnWu5-aJcn+{TRasYtY!NJc!c
zWOylU!y(0;fAdiYsy4yEa?X4t>pqh^&U=vl-Y3I-FEn)iq+E%8qdrV+4dCOez`pq2
zDrU}+q9DEuE9FX6{Z0kIXnHCJZKl;^aaQH*qDqG$CXOJ~kJfR|GzNh)lEpOHpg~Av=fWLkYza&`z
z-+`nwf8IFxo;1quJmf4qpVZuh0)@oE@3FN9m`BEQ6v$XkZ%d5ycwd7vd)Tw9s-}R8(CHqmpYhr=BP=6<66(g|``Kj%Ze;
z6Gx#trdFSAx-#EfTtO3WnY3;j%{Tpd7+1Y6f9;4Wet?vw0Kc`EO^MLdWB
z8I85I=$LsikwHs60rA9QLZiY66H&!n?Yx{A-7colDigeqlu#+FwKUI#WB17(?5|=X
zoexSCF7dB!9EYCof2d)M#qp#SDn&TK&t7RBsh;GCwy{;^6p~I}I
zf7ooZ22!$S;((r07uQP~OZp%QYi`QNoQ6hNf14G|iO!UE#E{2PCv{{-2J+%>C)^8)ZzbK(mu0Aad
z)@|186vn5|vfsvf0knu#MvzRLdR?LhnIjRSSTV@>+kx8#Ssoigr+ZIMU;EXAse
zbENIFvg^VG=g9LvJ+BgrC=ZF^yM>^wiXfWrG9KZ#_wmlWynDsx2W|HKarp{NZG{5$e^ji{iVZIU
zBAT0*9qjUv_UBW|TbGNQuB9C+G~KG2R2Fj{j;D;F;(dvRy|%kfa=flNPjYDY_G+#_
zK!0%(Z$!&@&qUuGz_FJ*l)&=a3-4FLDer~SWnG29p4{$h=X{O^KWv(h#4_9S(T(P<
zdFtw(k_SXG)dKSyxMFnFe<5Ss-vhQ^DFbsETa)@s;ONZSsWGh`52Un**tMthoye>E
znruICdv>=jFkhr|J|p^`;CyMRTYz~w`~{w=r0uRaIRoiC&yafFi>exYV8njxyWfwE;eiFe2KUO;r*3BXjvloo-WjGqHT>
z;Vl@_9D{38e=6P$T&|4W>+&Qo$ViWI+Ry^0>J+A-V#Wbbp_1pRo-BS%oM`>El)o&J
zx5{@NhHe?F#{wwXc?56@(-*uNt?1e|J%dAZv|~2>Id3JsRj$s5+yY
zR@thP(0M>jzdoW!`G2;f!8_@LLA2(%n$uG
zR)iBYcApUgpZyl>%W$^_3fmpv$9#*LjjvPg7Bf24!~Emo}li_uDSy1`nIzr-w
ze;ciArX_WcC?zMZ1$@XPotCALnRw;(ZH9;op`ft?tu(KdNc|*w=^aZoycj56QX;SE
z;z8EarO$E$KktupFV`9su&Xj*%`h?2A9CZ`bxYFM$CSzz)~qK%8Sbg
zX~P;RiQFPIe;&P%$HMj6d6}oZpRk+|p6=YY-CP*S+Z*9<
zwOoB`2>mpEXT^4uBJccE%C>UwG1Mehz7T5}_LNC9AaXzv!zta(kTKV-T)NvUbuG2wcv61z!C@Be-bCA
zgoa1T4nK;verk&3T3yWH#r!~FS#?PTk*aoA0QUrJqY)w0@i;G3i>qydfSi}&6hYpl
z5d7m13k|;M2~GAn&=^6?RO39ozNuG7K=hJeI{`{?qri(`tD
zFt$Q!Pd`+80eGa(*H0d&(Hg5{fA(f#31~iULKYJ&Wll<%7T(hSlJkl5xux$-QOV4&
zjJ3cHB3g`PZtP~321t^-m!+nLpnzZ<;dHx$Q0@BHdJIcOyXqfTLLY9X=2aP0q{(98
zxXgIU8iAZn2+?~@78E}EX_%1%k=~rDez!AX|HN7@-+U{QY}wxn9i1C-e{+a0a>mQ=
z1ivi8_zDqe=(K;4i~4rzvl*=x)?D
zt~PA4(r+>-u;3_q+UV^9NpAH+euCnja`-6IAucx-QQy)DE)r!EioZ|(QM7Z{PRm!*
zOggKycU!{xUJS?XHP#+&b_S>fd0n`1A=841)(s*&Zg0kUIdoW7f1qKX;K|6ep@(2Q
z&9(^pARbjq#^lq2#^rMRa0g}w=wqNRVs9UlPD=eWD=1iwz!E*39&(C!qSyulk6hZjd&han__OxXhl>|_?tk3T?CnFre>
z0gQ9Ug!}7Zrfm8ee+{`G9?x=<`QIjMK*tDH5PPzn#1AmozaPP
zS$>i9j9GDzoo4}tJ|8nF59uk%zF;87F5*e-1pK26B074;%<
zXm0vV?rp6T{05sGDXJ4+cF{ffZBr5VHQvlR2?+*l-@tSe{f0K~B|E8e`$z6Ays2`3
zXM6@=lIQ`He-0-KM6S_c4=V~3yUAmc?ZOb=QaF^lN$BEl!Yhv6_qpEkSIPMSp!Z4+
zsUI?(bo>}M|Dn?RhqEDc&ecKi-tVd|Edt^XsXc<1EhoDYi`aZ7N@~
zQyV$mP|og_WTukFsk^l`RjMTL3qN9xA_evL{{$e@B9qp7VNxs{y&v((*I2rk2%@kMxYf
z3sjA~x8^wxqThl!syy+oFZ!L)RkL5xKkQOcu66=7g8ty59AEX#zgm~%RG^_WScKY7
zU5kxcKvw6SS1z=0k#RlN8w`*k%ZICPvkO7sgb1Ch<@rW2o_nK~!7?aSjaa)NmoGwW
zf9xymr;_7@T8_~1Xqjw?9`OI+5VCa)(mvl9FPq=FY*?t8;jaur=~51WX(=2{O`2_~
z2};~0hGr+$`9xhiH%qIe8-R1+G%b@YRZuIIXk(!~Qhc8Z;x+Qn7*|TnPCj#1RgxSp
zRF|SxX?=S~>%Xp8WF;M(i7)o`r#x>@f9kfhyx%XI9>V@U8f&}e0mR4+EH|$U&!Uvy
z$(?9TUre5F*5W0GtQws@Xd@Q;!V7Qx5^^CaDbGAjw{5<88Rn$8dEt7YKKJ$rXRdZL7L}vR{GJg$H^?{cP%ztFUI0*C|67NKW*avRE7W97KI`&8>Z07PdgogEI29blAViG_JXB+ngS5-3J{{UjMn=qZcn
zv4*>iF>4w)vtv*$w>9Q#nA6pvzeXlyoM|WrA^6e~W1<^<4J7xz|CW2Af4Q2MZUzAY
zssaZB;{PANbICgWdp@dIS;r3W6N$G)do|eBM%s!}oxglZNK3k+O0y3}kVOP0I+AoS
z)U*$+#eaxK;oJZ2Vv66;!Z2EF!OSno;hNUMd_C<)$5<9GH?!OHW>-UxuircLE(Ac=
zUc^VezdnExoZaWvNHk3af6a)`u{t75iwXq9t|AT9U0hUQHzOjhw*$ry&g@a>UeZ8%
zXY$Z7eUk)&)gSIh-tR`#bmFiU4-}*^bk7Ds;_w<0@?w?VAqP3crG|kdDM5W0Ui!PU?D=52z
zRGOkyH}aFU4fYfcf08xXJqjtgm&W4qOh*ld)zh~l1XgnHX-)U@Y@
zdwPcqmCwGwobq)GF(VGhb%Oxe^4#I=L@1auAcMTfL>)L+e@0S!Qc|`UCXP;ySXlj5
ziA$#ZR&TsodQ6UA7tD+y(uOvB2X;SvHHX7r(cnhma&u>Vg5QC(2N7{2dxU1z4Ny((
zRsLASjzyrQ>=ocB93TIF-dp>WZV#x9iwTQL4~+1r4;AA3NwQz=3rYWmw!*i_>rQs(
zAPGS>x0wJZf9W_(GFD4U5(N~~v<9-yU^5DW;mX?An{DZ%GJy#th
z@#9qs?#>PB?j`Mrpthf%SaM!Rrwq20&H>r%h;Ei=4$+eb`On|d5Gvb&NHu>^qWdpO
z2>y>Lq2z4fZ1TTIVP!Y3kLt^%Yi_U=J;jJbzi_6Xe`&NZg<~zm#zHz;A_~|KE!H2R
zD^629#yGg5e-+1-&YClSUL!E!x#2E|qa_bX$oefmbHy3j{rPrrfe5q`{~Sn!+zUuC
z5i!|>A`C;bRYi+}9BmsXv894?=q%QcIIsaXh;c&|;n+@&PwI8de5(xFi?UgES+QQt
zsOSg*e`7V<2x%}ln<|-0s!dth5}BH#eq{K`nq6+v>5R=fV$Ozw6JYCRKE|Ru^{86N
z7SWtdjp`T-sm!Uhy7?wuxaBNPZHkZK#uU6cAoH{JQ|IMghBDDFVTrVo|4J#=PQFFc
zyVjXz+m5z*&Rq-#XDqY%r}+|fh|(f8I&Zvae`3`M0DtJd<4;abt#e1ptoBHw)tGy(
zP2iiDN{dvx(Yy9*EFvHw9IVSO0Xehzb5iCN*e!*F%D&
z^;nmlrzTF1TkTEx*fXL<2+kZNe{L99A(E~Uqz9Etywl&eUEgt?*s0-`Vi0%H1avf&@wzsd{R
zTY2f}yX~esU6Pz08Vf*38ibc1NmwaKhyh9Y8<4UCcKkwkmS9ovCVoVyS+sf8zzoO|-zV*fCkBO|xw{X3Yxv$VJ(K*MWUC2?r&4YaE}u
z@~3SrQ6HCp0ywjNEl3aW2>k?jzmivVBT$qf11&mUQ=#t%I$FGEcB#h#)=-90%
zw{PS_(@;+iXZx9-uvU(sx_}C
zAzs;s)-P3i7k%VRe||Bteh3%biyxs_-ck_fDh}mBAL^Ap=!Jhomt5Zr`iLD8xE?tj
z?|Hi1HK6Wf6yGhi|cE`aSL5{kls>8-HHx40CLO&SjfRpEe^?wuuB@@
zs{juWdD3Y)((rn0R>=};n0RFzf&eZLY~)Zp-2>q(o@}#SfAd#{r?Nnn&z6ThWi}An
zQRXFZd4)A*?;=gfCZ0&MLa&FPB90QT=KI4)>?xKbWw3SG(XqcL!F)eBaMds_y|oB4
zB#ae_b0?j`Cko}{8lh&?PI^9=rWolJP6#x=)Xuqs3FTysspuO?(oIhm-r&Zk8}Bq+
zUtv}#Oid~Jf7Lp}Bp6wL-hho=+&1HZE2Z6d;HUm
z(b2w@jo%ZUYDiMp$X7cze8MQfD3uXVofishSFJwS`?F=NX-Q@E?0j2&74^}pgWd4v
zP)g5@@bny^+R^3N6Y%N{ky3shOkKyTH3ALYd{%z>fAr2<53jn&AaM#vHzfe=m|lMM
z(SZYWoa=0ubWB#4;M=*eQ)!;wuXwbxLvR-nLJUBxu>R@7!HR;TMtQ>bOExRqIfw@&
zcART-dw2B>;ol4+B=uW5eAHVvt>9hi$1SQXY^=5QA3Z-qfH~LnR4t%PQ@G}HtufVE
z1-DG>e`fM-1j=qR^O7Rj03M(IJXPw{SUR~xOpe>yaU?D_O&+-(AZ7UQnm^gw=F?-6
zDw*#EaLIec<&9p#;CW#SmOZ-s`QVV=vQ6Eg-90ZCy#P%_
zGo(pa0mi`su{Q3fnnNA`qpA3d>=dqhDo08!e>OTbzkzUoumged%}3X5Ppqfn_rM1F
z5AEZ7S4awd8%qDw-l*>R<^tqEWQTU66(XVHZLMZ}9vTgz5Hb%Rb*4n(5HuBib-DzM
z0Q7{(UzB-hInDafn33I+#8=S9Ms~9Y6yOHX7CLA)eY$F9&Ke27kf-63xkS~VDHO}8
zf1y*?gMl+WdGHsHPnlG$RciE#PB&Bzg;a9nR$@Hu%zk5_89S@I>1+LX6M|3
z0A>w|K?9wQdberT!$b+-(0E*v5L|5(3+u3d3_1!+6D3y(DkF;}yR
zp)wFhHV!VF!NExZMe=kju7bGdu<76Z~cmcB?s*eyp%7&F6_Ws>e
zp>C`$ug$a%uNw@?%3!66%`&L0?X!#3<8pTLh_q66wUJpYPPGK5D#a`mPu0DqX96+R
zXy$+N+$usvJe;eRJ#;5`i7BU94;%NAh(m-jG=tPEl^-FxvV+kCqZ+GDkz{l9e=WAD
zAS{b#q7xJ^I=6B{wyRa0nbfF7QN*(m2ga#VcceWuN+Gz-_kZWic($i!Oxl?GQcx0yeP}m`pIq#9yq!bIin~f>HGf
z#A}rw{SieiQiHD^r3RZ75uKy2ER!eDr!QvPiIjlB-%Q%l2oEJJ>8X0n0Wc>W(C9
z0zX?_Pd-^W)WB2iZoJX2t9Ow23sd<7VSDl*c(b+E0jH($RM!xr%=weWe@=#{XcZk)
zq(xFOl3>9ehq~Ie$F1XxxB^4PI6e=VKeNML5P>~3lvW9%QKWXcswQw1F#&VC@ZS!dIobf-htY*OUJo~ku
z6b7_~v`Rpm0|=vB?*DwOgui&o%Q4u`A$~pEHWhyJ{3R!@m60VSnXuhEKTkb>7~OtZ
zTa*3#Z3H~1*CI*V_rnA_X^z)7h#kr9K#-(Lc<1+6?1Ipgj<_o3e>Na&flx9=vBgZ0
zkc&cK6vi5z)3k7#s>`8>rmlEmcg%SXa_O+Qx3i0aikWnt!#f5KfT^6c$;^-oI4dS_
zRRUoIm*kymTa@tfz?Op_OflyL#fg(g;F#EWDvKL|v~cB3{XtXtkm1bcVZH(aTJO52
zx7S|#Mj~4{^VLsbe@xEXIb3MRP}<7cPjM#A?oAIZastqVS6#>qjyoQDFX-=C8MPl>We|emtX`V`?sn%+QFPCh#kra+7q{d_4HYKHk2TwX3Ax2
znAZKQp;>~*UgFpwB_3~PQMVFkW?qvcCO%5S0v0QLk?)ttAus7+sP{ICg!72p8O%8Gy&F7tud4(sY#R$
zbQ^6I(}|>Vq$9wJWNRlRi2IbC`(EG5R(1*iVzfebD$fn=8It3TOG}psdjWt^t}m>p
zf@hUUW3#~ytlm`W=sx_6WmhzLZ-fds3)25nMqC;WmBwiEs}bvu?5=XrQXGfL`(s#I
z`W%y4f5N1_sjBnTu~LNn4XlG?uQS#9Uk6!
zKR~MBx22qO$*Y$vT7+E0>scdk8*oNJMG4~Q)T?epMFA<4nf2GUoMXRQPT1aPRi?e0
z#lxaIr7HpfjWbpDDHduL3{vz`14Oh+19mjLe~B0i+
z@&swp*sw$izIYH~rB&tV)CMeUYEq`eJ!3@Xo-RU`U<+&X%&IzK;vo^Kut_4OR0+yV
ze;aavO;Z-O*r^qDtaxyd@o;4%4T++JDKm!e_bLV~JS38u*;gUekvxtlL+a)z#~2uA
zFzX2F`f-$Fh`;vCFt$d)a0;?TiHDY?F)fbafeLnwfs&1P{4mCYX0(So_tY9+bXDKo
z1KA}|;9Vg6=|f>a`S$ZO>lMCV>P$3_e_8f0jynmFZpqz|ckpoLDin_0@~c$0l#yM5
zOn1idDgR&<(KW1V^6(1r$jaRlHh*;MKhExUv#pWqpCO)&fETVObCT-V@y)-^g;}Ak
zGvQXhyKy{1hp+YBEH|am2o#6N_kG1TP4{ids}ox{B+W4#Vv$y4H+dIV#0xxMf6=46
zdJ)Vw<Pmb6&++AVs2$FCo
z<`&nTtO;X(19S24XO1FkJGkIb=#q@q=b(a#;=-_;LR?k`xDXAmr4e#3|w
zxO3s}&J&;CUcA9$_rxEYvUBSnc(HV+?o{6Se4t0~NTK(@H-vf9w*i^jf0?Z?k79Yp
zt{vY!(%c_JquWtpe?u1>x*;vPe8}PSNFThvZDIF>?o`~pzkXtWQ~C)UAntem$Vjk0
z;Gjly%DT@rfI5JT|6w6jKl~mxp%7xhGx$CQ64<(6{(ygOdko}wKT7m5s-BW$1r+88J8`bXikmckZywsEHHRTI&1ahbihwue#2V!~U_;csx{ZYrM3YX;5=%aZ_=lS3hg)
zVY`>F)Vg4e#7c&miB5-ZzzZZ0kf^(-*`Ov=7$dl>&)p)j?dm9JjrXaN4-+f91?&)9
zf4Cem5s|rRa(+0>F&?Mz-=z=jWb5$Nd8iO$bA*@
zE7Y249trwQ^d7p|bt-}yn>N;0`A!5EDacIAdzbuXw&_%=b55q|5y79Fbkk+#0kxtH
zHDaqATt-!uf41h;y2zi5yuLe%pI1?ftnZICs1*mk6+CbEeV*pa7RZ$exqCEi7r|@h
z(V>3gf!6NB5CjkdHE}U)J&-S|MC*8TG%?>P8j<*J1vk&z*HzVWHComyY<79=6%?()
z)oO1+S(stB4RW`aAAUT#D{ZdsAE-TN`E!E=k2kXYf8@aOkA;q+ZnIi*XT_-_mmK0y
zbuR@!O)PCJb>~_eu~)o1XF>`L%BrPYv2k8-3b)hZio=c{>lCKbHI=l~DD)ah2#{?a
zZLjZY7+agnMYSm}tezwZcsdN;=Lec!X@y@e?Vic0dms~~$zEPT`b>K&xMwL%X9F|`
z3t^LMe{RoyGyIY1kc0G_uUGrYlE*&Rr%rvuTsu|uofjhbbCXO-so^?^d8@IqIX}PI
z06C+!J-?hRVJc?2nT1uY(%iPpytJyu9DT`k9`D(g`Dwn-%2KX0r|7i8_n5NsPZ-c0
zURg`iNXOPfnO|42xe&j+!`qYhao%<#*t(95fAevrowd2Ors_`(yieu?L3rt-6`8`^
zwfG5h>w36Cu(d&EXQK|>j+nYxQp4O;d)3?zSHh3z?f`aHcDl%n?wfb>a5n^@vxknZ
zt?Fric9Me=4PlTR+ZHJ0`}&~nDlZ8z0YfDhr-|~2_GEJ{7p>69W(K{B691k8wTq0%jVGCZ<(h72AP9@T<#y6LEMnoMW|GVxT>nMAtj7>ia(p>YPu!d(3~W_nEW
z8HWbHZV8Gp*UusZ&wkj05C?TWjpdVZe-`-?x%A_SMuC#Q9+L6s^;pE&lnWZx%@UEu
znluZ5^y&CB?evs!XZ%e1d8Tx_IEywJYU6f=l4Pc;go7$mR$?8}JKAB7{Kgbo9dfWB4Q|5!p4;gjMa$4+;}K|^b2+=;y1_SAf?8f
zxUziW=*|5X90$8oxQAJ*RpKA}e^5_=)7Bw_J(;FFFiUE#La}@pnER(AY8yzbe+JRU
z)RG~)BGfy@(_RI7AiMeo(MHz75?gx&RfW~UX2*>4NjR1Ws}R_q#4YmG8re)~n(@<|
z2Z{{#v?40jm7;UgoPiFVsjox21T1qe@tG4wvT)&<9~^N=L+Xn{W&Fw4e*jW_H!vZn
zbi@x*;Q_0lX5?WgLCjU?<{?pIv~*-+=s8spm2ZpL%1chbk`z@#%(>o30aY>n9hW3SiR
zb9KcCS_O6w!V4B(Yp_rI>zuoa#c|KrUf6)%EclV|wK6%R$*2uje;M8spijnMBt#E!
zM7352i5N)t1CkT&h*?DoSfGdQ!&06N08g*i2SsbGB@Dk;UyXQcMrw5%@I2%R(2CLS
z*hMF5`Dy=<&312Ld4-7)fZ%LnN$&ys6xW&j=ak3u%eQr4R>8*n2P=z=o2I;6bzIYM
zoQnBqMrjS36Li4}f5!s4jTmfwIED=q^aIiAVbO=_Bt>EL^3%_GNl~2`+pRFZ@uwdJ
zPw4xfTm*!Cm;u{J)?}_YfT!rf5+z6a1fhU+U9rJA3JputMgy%uu}?ikH55ImL|
z*EyoAH&JJ{b`vlRsj}u*XRb7v{<-K1+O#EbnLMc5Ls)~pkP9!t^q+>YY-PO
zAU}ds(b^ih=AJe~F2tFMaIp%6nT=ETCHyK!|mO+j}wou&;YW9q+
zdDK{o*w@stKIWFd-lV6RnTfFSc6)=gS?duabtP7+)=c4+s@??1R89Cr-s-?k%ITWA
zit8l>fB12KLJ*W0q7}Nq)#wf2PKi&G0e`Xp@6uDyX88T{WNX|C=1Oq2W7iyQLs|}bT`7=(gFn}9!h9qJaibb3Q`cnH)xppCx
zy6m1TNg%M27p~>N^f@tPz#g*1t-z5&JaZ>G+{%MrgByjtuj53s#8}hbsgnZir5ZoM
ze|?Z^g^O$fJK){E|9YnJ-XfD&eT3X_t>XNN1EzXrkhANCtr>h}Aet
zQ9HVj3F%!vTf;eN{ICB>ex6@`hy@S4e~&cyWj}`M_@ewEUx{8da!2u_D%rLyxCoIk
zykKmjg*DjW%=ktPwd{x9@}YQr=+-%zD2j)(lIo?8sHja+!&SsKj|`KM-N37u_6Ttq
zd>LKII;3Lqqf(GdR8QP_l0~L5+i|jB(X%8-G!1@0RW#OD%w1qgwT0+Vo1iJ;e=ETv
zxULI_{HR#Xm_adQ>GDS%SaoUL8vz*`QPQW0ldhd9cKEgVs|5(ev5+#ZU!71b4P?y*
zp@;!}6n^z&m_y)Mf{?wgi(G(wn*j8XT#1mq!KdCS8qAQQCL?Tm5d%1pI7WcK&lhuP
zE&J!MO9(>l4pDb-qn7#&86Xp0e|QC!c*r>tSrYc%
z!`GQ~2xmfDy2J#=R!_-3xA0!L!@k1mDlk*zPM5|vD1sn)$cwp-mu)4}uy4w9da;hb@9a{E=kr?@u2Kfl63#lZ&c~XuIhOYF
zx8b`)5CWEm({0@CudvQ2-mn~2_Y7=9wS|+Cg+~TmLc?qfH6`K72j6I)m?4Ml+&L>)
zDNghDO7UTkw`o*~+`3A5zp?eul}DO(ox(%{@?60ge%u3k7+cN=e|SJLn1s?LgUsCi
ztF%OCm4u(9Qv8isXwkUEYDRe7LEBqBBqWHcVj++gd~a+Ty%+1SBTUYE(j-TUmonY^
zKuO9(cwJV4jb$52$Pt8$fgDX7Bb2c?xfULzKA>A)iE3I`4&T@za4;IC2_OtM#iNS*De0
zqkwxR0DA(wQe~qr3Dz3@K88O?xuBbP(47D(&v~4-{W_L*S&64!^Q1kj*_mT?PEL_$
zn;+A-v&LY~EawSde2|N45z)q{>&q2u5#=97dCCVvuxb+Tz
z3P!J6;J^2oh
zxJdH^e{1H3IE(VDbN{3oXJL^y@-tv9$S_H`m`SnEC*ojidrczjNJ>pnQ>`r&ie)Esnv0mL80aJj#Pr!P*9nP3%;
z7wVXHMALf&({G02-{dJD^hy|cDA_`K?6^kheA~(raS8P#BR^J9!+6n08I=h2GC}J`fc9`{w4*@})4=ZG-&M!k
z@dp^13R>1fUjz}lfUW}fra#h72(bnU3Q~#NB{kKda<&k|<&x9V-sx8egDD0$a$piY
zf3Rhag!9u71K+$wP^+0h)v&guR3~m@Fd`f*skSO(GTUeFF<6n
zjMM`@sAthqaDSz`h>|I~Kxe#QbO_x_e^m~rmpY&u->#L`LEXDMB#HgbkI%HEDd8xv
zqG4k}myRB~W0@9>E-rPzx6F#go{(WJ4;eNsV}uNzUhavG8(veKvDR@Ci45%jQ6oSL
zJC~4LT1+J+9FyN?$W=o8X#{8SBLO=i%7Qu}cNAi3gLttSvuUZInT(^PxWuR)e;XTA
zktEtIMVUEr8%Fq+sxD+$*w?4UTnAAJA)v2wY(tfeHT_~P|4Q#eik3Brj+&}PII||^}CQ8{r
zzvmJAYEF=Ik8w<%)xuMvh<>jtz(Q<=C0*bw4rR`FR|D2G->z{R}DdyYehe!BtJ!hnBTbH}*
z$&@Ml+>2_?E>85V@V{h;e^+q;2@&V{4KY9K#1=T*;o$SCPx>-IivJ6X2g;-qBjwhn
zHp(tk<%6a*AQ$xJHv5*5KbCg?q`~VA{1U1su4|A!f@f#1OX-C?nm3;`0^atAmq=YC
zJv_-8Fqx#ch5E2BVb4jGq1Mq0Px6;=^tFpM=Xk*laxCY=`yPADf6FOjIZn8V5^Gh?
zTg(gYjYEVD(JSqmK0#5W3K|{#{6s@S^#&wLSqZT=Go)3izJW6^c^Txcn_I-f567FG
zU<~QSk3QegC277+Sg|m`B>5#oD6^jszqg21wSLzAf-E+)?+;4ovvQ;lzIsIZzBJem
z7#`S7AcStn;fJnPe+9b`MPFFuJ1qmU9{BY)9eeT}ME>KK-r^6w)`)LZ+e5@&n-9Xv
z5ub11FDTr-pFNhpMxuD%8OcN?MU}XB`And48c^%Jtn}X@q|i*r}26(?QdfBAvKKO`%CVd`IJ3}F1&
zU^bLNHPlB6p1#aD?Y>>MwwPR03U2GTNV9O)iA2JTNX6%BdLsrCVZ^
zmvTMXUC*Gef2z$M{^YaVr|eI9qF3snTkj)POsZzr`=tq?TXvtq%1r6H-+t`69f(2$
zwxg~b#P~jv@vH-$P+xp2^?I+lM}T<2>swoQj6{<36r@cTSnoW;MN}SMHUm!GJL-YE
zBAHkU6Qb7PyY#SN6Hgk-g}~5C^A+jmaEYJI1d5PBfBb&|AofIe
z6%wYGf5*0k@9ViYxp2f2Y>VjuyAwyB)rkwe#Bt|$N2&av#T@nv=6h!w-geXH^20d3
zeaTDl1B(6-j_M-lJNtN<9peuH`UbT=@(Xf$+t~&Aa%&CogIIa+>!tm0f&+X9$-iRU
z(tnYCr1}m0@|!Zfvs+XA!qb|GZD3ZO_Ee76e<>`f=PeK1sxD~&J!e?1iP6t3OOMdO
zD?2P*lgj6kN-vaC%vjW}^OYMw5ujMT4Uz3>dZllSn4wiIM!Fogze54lrX7}7$~ZbF
zwgsbg+Z}f#L*b0^!A^?b52cKb5cM{N-C0QN4%Q6z0R?9xqrSszr0@YfVsl+yiA!~b
zf1`@&tCrE1YIfkrq?ZpZGhZD9y%mM}!V91`+M!uYk1G)C5exN8?@ju7C-O-VQ`+{U
zd{J3B#({l1|GN@!k2s))+5e@bXAjgZ=HX*s+3Psio)W9qt%}#viP%k~gE`o(gXbip
ziXjxB360PMGhDv3t87(3tlo{>cb`1Bf6tT+bdbzAu8!@`B!@+Buu0nUI^`PE)r!~(
zCY<|<(CfyPB@^jyCWMIyo?;fL8oQb5soHMK@_F1dn3~brVB>0Qi
zwjj-YpPVug*_%oRAV3RZUJd41^&u+~?j*yaz^W7tqyny>c{tZxcoP*^XDd)ie>b=u
zp}wIXaXyT674FGF#aNpH6(nOHq#zjN0g^8T6^+#;Fnwxm#)TUzP!#@2=V@qkhnCj&
z;4gb6=&nVm^d#JkEuaKZc+9?@#MN25mP7d0IH5d!Z0)sBR+sXR>_aXL}5l|
zgb0qUgTgeE2;yfnT7-x-sX0j=j-fN{%A_=BIi9w++`>sbmM?EyKin5a9KUQ#zcMDf
zxI7xvBz-<8X2CI`*$)n8L+&Lk%1Dw?&+-8DA4lX6G0e5AEJ#Yyy_lI05o?&+I7T1+VNCFH}I4me}Wm@P~&CsTWn)r82HuZ0vs}=cE{vT8y{$qsy
zow&n4fnEPm#rR)2!2XLv`oESv{#R4P{ujr=|FT~4?{WSv1M$x}fBpAFA^slt@1g|%
z3_J$%Ka(i@ZvPVj0^ye$iz`O|e^4I&
zceuY--2M|T6YGCcf2$x34)Kpo4GWa`7Zq0jZ4Uq608mQ<1e0w-8nc2vxC0IntPMxW
zqL~Z@K>z@OMUzNENeMAR002@hba-@=%t9QKwn7d9;6szfLNEdZM3eYJHv%t2lQBa<
s0&Yc@asU7T
delta 15929
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
bb1zU!1qJ{B000O82mr$Y008Yl00000AC|?*