Example usage for android.graphics Canvas drawTextOnPath

List of usage examples for android.graphics Canvas drawTextOnPath

Introduction

In this page you can find the example usage for android.graphics Canvas drawTextOnPath.

Prototype

public void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset, float vOffset,
        @NonNull Paint paint) 

Source Link

Document

Draw the text, with origin at (x,y), using the specified paint, along the specified path.

Usage

From source file:net.simno.dmach.ui.view.SettingView.java

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawColor(backgroundColor);//from  www  .  j av  a2  s. c  o  m
    if (!TextUtils.isEmpty(hText)) {
        canvas.drawText(hText, originX, originY, textPaint);
    }
    if (!TextUtils.isEmpty(vText)) {
        canvas.drawTextOnPath(vText, path, hOffset, vOffset, textPaint);
    }
    canvas.drawCircle(x, y, circleRadius, shapePaint);
}

From source file:com.semfapp.adamdilger.semf.Take5PdfDocument.java

public PdfDocument createDocument() {
    //create new document
    PdfDocument document = new PdfDocument();

    // crate a page description
    PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(A4_WIDTH, A4_HEIGHT, 1).create();

    // start a page
    PdfDocument.Page page = document.startPage(pageInfo);

    can = page.getCanvas();// ww  w  . j ava 2s. c  o m
    Paint paint = new Paint();
    paint.setStrokeWidth(0.5f);
    paint.setColor(Color.BLACK);
    paint.setStyle(Paint.Style.STROKE);
    can.drawRect(1, 1, 594, 395, paint);

    /**
     * Page one Text Fields
     */
    drawText("Job Reference:", 9, 21, FONT14, carlitoBold);
    drawText("Date:", 354, 21, FONT14, carlitoBold);
    drawText("Time:", 473, 21, FONT14, carlitoBold);
    drawText("Location:", 9, 48, FONT14, carlitoBold);
    drawText("Task:", 261, 48, FONT14, carlitoBold);

    paint.setPathEffect(new DashPathEffect(new float[] { 1.5f, 1 }, 0));
    can.drawLine(85, 36, 350, 36, paint);
    can.drawLine(386, 36, 468, 36, paint);
    can.drawLine(506, 36, 585, 36, paint);
    can.drawLine(59, 60, 256, 60, paint);
    can.drawLine(291, 60, 585, 60, paint);

    if (mEditTextValues[0] != null) {
        drawText(mEditTextValues[0], 98, 19, FONT14, roboto);
    }
    if (mEditTextValues[1] != null) {
        drawText(mEditTextValues[1], 65, 44, FONT14, roboto);
    }
    if (mEditTextValues[2] != null) {
        drawText(mEditTextValues[2], 297, 44, FONT14, roboto);
    }
    drawText(mDateString, 390, 19, FONT14, roboto);
    drawText(mTimeString, 509, 19, FONT14, roboto);

    /**
     * Section One (Stop, step back...)
     */
    drawHeader1(8, 69, 202, "Stop, step back and think", 1);
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeWidth(0.35f);
    paint.setPathEffect(null);
    int left, top;

    //draw left boxes
    left = 177;
    top = 108;
    for (int x = 0; x < mCheckBoxSectionOne.size(); x++) {
        Take5Data.CheckValue isYes = mCheckBoxSectionOne.get(x).getCheckValue();
        float topLoc = top + (x * 33);

        if (x < 1) { //allowing for different 1st row size
            drawBox(left, topLoc, paint, true, isYes);
        } else {
            float newTop = topLoc - 6;
            if (x < 3) {
                drawBox(left, newTop, paint, false, isYes);
            } else {
                drawBox(left, newTop, paint, true, isYes);
            }
        }
    }

    DashPathEffect pathEffect = new DashPathEffect(new float[] { 1, 1.5f }, 0);

    drawText(mCheckBoxSectionOne.get(0).getHeading(), 13, 113, FONT12, carlitoBold);

    for (int x = 1; x < mCheckBoxSectionOne.size(); x++) {
        int height = 132 + ((x - 1) * 33);
        drawText(mCheckBoxSectionOne.get(x).getHeading(), 13, height, FONT12, carlitoBold);
        paint.setPathEffect(pathEffect);
        can.drawLine(10, height - 6, 222, height - 6, paint);
        paint.setPathEffect(null);
    }

    /**
     * Section Two (Identidy the Hazards...)
     */
    drawHeader1(230, 69, 345, "Identify the hazard(s)", 2);

    //draw right boxes
    left = 542;
    top = 104;
    for (int x = 0; x < mCheckBoxSectionTwo.size(); x++) {
        float topLoc = top + (x * 20.7f);
        Take5Data.CheckValue isYes = mCheckBoxSectionTwo.get(x).getCheckValue();
        drawBox(left, topLoc, paint, false, isYes);
    }

    for (int x = 0; x < mCheckBoxSectionTwo.size(); x++) {
        float height = 105 + (x * 20.7f);
        drawText(mCheckBoxSectionTwo.get(x).getHeading(), 238, height + 3, FONT12, carlitoBold);
        if (x > 0) {
            paint.setPathEffect(pathEffect);
            can.drawLine(238, height - 4, 581, height - 4, paint);
            paint.setPathEffect(null);
        }
    }

    /**
     * draw section 3,4,5 (including checkboxes)
     */
    drawSmallCircle(8, 331, "Assess the level of risk", 3);
    drawSmallCircle(202, 331, "Control the hazards", 4);
    drawSmallCircle(398, 331, "Proceed safely", 5);

    /**
     * Draw Page Two
     */
    int xLoc = 7;
    int yLoc = 420;
    int height;
    int width = 565;
    int RADIUS = 14;
    float INNER_RADIUS = 13;
    int centre = yLoc + 7 + RADIUS;
    width = xLoc + width;
    int middle = width - 340;
    can.drawRect(1, 420, 594, 420 + 395, paint);

    paint.setStyle(Paint.Style.FILL);
    paint.setTypeface(impact);
    paint.setTextSize(12);

    can.drawCircle(xLoc + RADIUS, centre, RADIUS, paint);
    can.drawRect(xLoc + RADIUS, centre - RADIUS, width, centre + RADIUS, paint);
    can.drawCircle(width, centre, RADIUS, paint);
    paint.setColor(Color.WHITE);
    can.drawCircle(xLoc + RADIUS, centre, INNER_RADIUS, paint);
    can.drawCircle(width, centre, INNER_RADIUS, paint);
    can.drawRect(middle, centre - INNER_RADIUS, width, centre + INNER_RADIUS, paint);
    paint.setColor(Color.BLACK);
    can.drawCircle(middle, centre, RADIUS, paint);

    paint.setColor(Color.WHITE);
    can.drawText("SAFE WORK METHOD STATEMENT (SWMS)", xLoc + 31, centre + 5, paint);
    paint.setTextSize(16);
    paint.setColor(Color.BLACK);
    can.drawText(String.valueOf(4), xLoc + RADIUS - 4, centre + 6, paint);

    height = 50;
    drawText("What are the hazards and risks?", 25, yLoc + height, FONT12, carlitoBold);
    drawText("Risk\nRating", 267, yLoc + 47, FONT12, carlitoBold);
    drawText("How will hazards and risks be controlled?", 319, yLoc + height, FONT12, carlitoBold);

    paint.setPathEffect(pathEffect);
    can.drawLine(262, yLoc + 45, 262, yLoc + 320, paint);
    can.drawLine(302, yLoc + 45, 302, yLoc + 320, paint);
    paint.setPathEffect(null);

    float currentItemHeight = yLoc + 75;
    float padding = 5;

    for (int x = 0; x < mRiskElements.size(); x++) {
        int textHeight = (int) currentItemHeight;
        float totalItemHeight = drawRiskElement(textHeight, mRiskElements.get(x));
        currentItemHeight += totalItemHeight + padding;
    }

    paint.setPathEffect(pathEffect);
    height = yLoc + 350;
    drawText("Name/s:", 12, height, FONT12, carlitoBold);
    drawText(mEditTextValues[3], 55, height - 3, FONT14, roboto);
    paint.setPathEffect(pathEffect);
    can.drawLine(50, height + 12, 580, height + 12, paint);
    paint.setPathEffect(null);

    height = yLoc + 372;
    drawText("Signatures:", 12, height, FONT12, carlitoBold);
    drawText("Date:", 468, height, FONT12, carlitoBold);
    drawText(mDateString, 497, height - 3, FONT14, roboto);
    paint.setPathEffect(pathEffect);
    can.drawLine(60, height + 12, 464, height + 12, paint);
    can.drawLine(492, height + 12, 580, height + 12, paint);
    paint.setPathEffect(null);

    // finish the page
    document.finishPage(page);

    int imagePageCount = 2;

    for (Take5RiskElement risk : mRiskElements) {

        if (risk.imagePath != null) {

            // crate a page description
            PdfDocument.PageInfo pageInfo1 = new PdfDocument.PageInfo.Builder(A4_WIDTH, A4_HEIGHT,
                    imagePageCount).create();

            PdfDocument.Page imagePage = document.startPage(pageInfo1);
            Canvas canvas = imagePage.getCanvas();

            try {

                Bitmap original = BitmapFactory.decodeFile(risk.imagePath);

                Bitmap b = resize(original, canvas.getWidth() - 100, canvas.getHeight() - 100);
                canvas.drawBitmap(b, 50, 60, new Paint());
                //                    canvas.drawText(risk.getOne(), 50, 40, new Paint());

                Path textPath = new Path();
                textPath.moveTo(50, 50);
                textPath.lineTo(canvas.getWidth() - 100, 50);

                canvas.drawTextOnPath(risk.getOne(), textPath, 0, 0, new Paint());

            } catch (Exception e) {
                e.printStackTrace();
            }

            document.finishPage(imagePage);

            imagePageCount++;

            new File(risk.imagePath).delete();
        }
    }

    // add more pages
    return document;
}

From source file:com.android.screenspeak.contextmenu.RadialMenuView.java

private void drawWedge(Canvas canvas, float center, int i, RadialMenu menu, float degrees) {
    final float offset = mSubMenu != null ? mSubMenuOffset : mRootMenuOffset;

    final RadialMenuItem wedge = menu.getItem(i);
    final String title = wedge.getTitle().toString();
    final float rotation = ((degrees * i) + offset);
    final boolean selected = wedge.equals(mFocusedItem);

    // Apply the appropriate color filters.
    if (wedge.hasSubMenu()) {
        mPaint.setColorFilter(mSubMenuFilter);
    } else {/*w ww  .  ja  v  a2 s.co m*/
        mPaint.setColorFilter(null);
    }

    wedge.offset = rotation;

    mTempMatrix.reset();
    mTempMatrix.setRotate(rotation, center, center);
    mTempMatrix.postTranslate((mCenter.x - center), (mCenter.y - center));
    canvas.setMatrix(mTempMatrix);

    mPaint.setStyle(Style.FILL);
    mPaint.setColor(selected ? mSelectionColor : mOuterFillColor);
    mPaint.setShadowLayer(mShadowRadius, 0, 0, (selected ? mSelectionShadowColor : mTextShadowColor));
    canvas.drawPath(mCachedOuterPath, mPaint);
    mPaint.setShadowLayer(0, 0, 0, 0);

    mPaint.setStyle(Style.FILL);
    mPaint.setColor(selected ? mSelectionTextFillColor : mTextFillColor);
    mPaint.setTextAlign(Align.CENTER);
    mPaint.setTextSize(mTextSize);
    mPaint.setShadowLayer(mTextShadowRadius, 0, 0, mTextShadowColor);

    final String renderText = getEllipsizedText(mPaint, title, mCachedOuterPathWidth);

    // Orient text differently depending on the angle.
    if ((rotation < 90) || (rotation > 270)) {
        canvas.drawTextOnPath(renderText, mCachedOuterPathReverse, 0, (2 * mTextSize), mPaint);
    } else {
        canvas.drawTextOnPath(renderText, mCachedOuterPath, 0, -mTextSize, mPaint);
    }

    mPaint.setShadowLayer(0, 0, 0, 0);
    mPaint.setColorFilter(null);
}

From source file:com.googlecode.eyesfree.widget.RadialMenuView.java

private void drawWedge(Canvas canvas, int width, int height, float center, int i, RadialMenu menu,
        float degrees) {
    final float offset = mSubMenu != null ? mSubMenuOffset : mRootMenuOffset;

    final RadialMenuItem wedge = menu.getItem(i);
    final String title = wedge.getTitle().toString();
    final float rotation = ((degrees * i) + offset);
    final boolean selected = wedge.equals(mFocusedItem);

    // Apply the appropriate color filters.
    if (wedge.hasSubMenu()) {
        mPaint.setColorFilter(mSubMenuFilter);
    } else {//from ww w .  ja v  a  2  s .c om
        mPaint.setColorFilter(null);
    }

    wedge.offset = rotation;

    mTempMatrix.reset();
    mTempMatrix.setRotate(rotation, center, center);
    mTempMatrix.postTranslate((mCenter.x - center), (mCenter.y - center));
    canvas.setMatrix(mTempMatrix);

    mPaint.setStyle(Style.FILL);
    mPaint.setColor(selected ? mSelectionColor : mOuterFillColor);
    mPaint.setShadowLayer(mShadowRadius, 0, 0, (selected ? mSelectionShadowColor : mTextShadowColor));
    canvas.drawPath(mCachedOuterPath, mPaint);
    mPaint.setShadowLayer(0, 0, 0, 0);

    mPaint.setStyle(Style.FILL);
    mPaint.setColor(selected ? mSelectionTextFillColor : mTextFillColor);
    mPaint.setTextAlign(Align.CENTER);
    mPaint.setTextSize(mTextSize);
    mPaint.setShadowLayer(mTextShadowRadius, 0, 0, mTextShadowColor);

    final String renderText = getEllipsizedText(mPaint, title, mCachedOuterPathWidth);

    // Orient text differently depending on the angle.
    if ((rotation < 90) || (rotation > 270)) {
        canvas.drawTextOnPath(renderText, mCachedOuterPathReverse, 0, (2 * mTextSize), mPaint);
    } else {
        canvas.drawTextOnPath(renderText, mCachedOuterPath, 0, -mTextSize, mPaint);
    }

    mPaint.setShadowLayer(0, 0, 0, 0);
    mPaint.setColorFilter(null);
}

From source file:com.googlecode.eyesfree.widget.RadialMenuView.java

private void drawCorner(Canvas canvas, int width, int height, float center, int i) {
    final RadialMenuItem wedge = mRootMenu.getCorner(i);
    if (wedge == null) {
        return;/*ww w.  j  a  va2s .  c  o m*/
    }

    final float rotation = RadialMenu.getCornerRotation(i);
    final PointF cornerLocation = RadialMenu.getCornerLocation(i);
    final float cornerX = (cornerLocation.x * width);
    final float cornerY = (cornerLocation.y * height);
    final String title = wedge.getTitle().toString();
    final boolean selected = wedge.equals(mFocusedItem);

    // Apply the appropriate color filters.
    if (wedge.hasSubMenu()) {
        mPaint.setColorFilter(mSubMenuFilter);
    } else {
        mPaint.setColorFilter(null);
    }

    wedge.offset = rotation;

    mTempMatrix.reset();
    mTempMatrix.setRotate(rotation, center, center);
    mTempMatrix.postTranslate((cornerX - center), (cornerY - center));
    canvas.setMatrix(mTempMatrix);

    mPaint.setStyle(Style.FILL);
    mPaint.setColor(selected ? mSelectionColor : mCornerFillColor);
    mPaint.setShadowLayer(mShadowRadius, 0, 0, (selected ? mSelectionShadowColor : mTextShadowColor));
    canvas.drawPath(mCachedCornerPath, mPaint);
    mPaint.setShadowLayer(0, 0, 0, 0);

    mPaint.setStyle(Style.FILL);
    mPaint.setColor(selected ? mSelectionTextFillColor : mCornerTextFillColor);
    mPaint.setTextAlign(Align.CENTER);
    mPaint.setTextSize(mTextSize);
    mPaint.setShadowLayer(mTextShadowRadius, 0, 0, mTextShadowColor);

    final String renderText = getEllipsizedText(mPaint, title, mCachedCornerPathWidth);

    // Orient text differently depending on the angle.
    if (((rotation < 90) && (rotation > -90)) || (rotation > 270)) {
        canvas.drawTextOnPath(renderText, mCachedCornerPathReverse, 0, (2 * mTextSize), mPaint);
    } else {
        canvas.drawTextOnPath(renderText, mCachedCornerPath, 0, -mTextSize, mPaint);
    }

    mPaint.setShadowLayer(0, 0, 0, 0);
    mPaint.setColorFilter(null);
}

From source file:com.android.screenspeak.contextmenu.RadialMenuView.java

private void drawCorner(Canvas canvas, int width, int height, float center, int i) {
    final RadialMenuItem wedge = mRootMenu.getCorner(i);
    if (wedge == null) {
        return;//  www  .  jav  a 2s  .  c o  m
    }

    final float rotation = RadialMenu.getCornerRotation(i);
    final PointF cornerLocation = RadialMenu.getCornerLocation(i);
    if (cornerLocation == null)
        return;
    final float cornerX = (cornerLocation.x * width);
    final float cornerY = (cornerLocation.y * height);
    final String title = wedge.getTitle().toString();
    final boolean selected = wedge.equals(mFocusedItem);

    // Apply the appropriate color filters.
    if (wedge.hasSubMenu()) {
        mPaint.setColorFilter(mSubMenuFilter);
    } else {
        mPaint.setColorFilter(null);
    }

    wedge.offset = rotation;

    mTempMatrix.reset();
    mTempMatrix.setRotate(rotation, center, center);
    mTempMatrix.postTranslate((cornerX - center), (cornerY - center));
    canvas.setMatrix(mTempMatrix);

    mPaint.setStyle(Style.FILL);
    mPaint.setColor(selected ? mSelectionColor : mCornerFillColor);
    mPaint.setShadowLayer(mShadowRadius, 0, 0, (selected ? mSelectionShadowColor : mTextShadowColor));
    canvas.drawPath(mCachedCornerPath, mPaint);
    mPaint.setShadowLayer(0, 0, 0, 0);

    mPaint.setStyle(Style.FILL);
    mPaint.setColor(selected ? mSelectionTextFillColor : mCornerTextFillColor);
    mPaint.setTextAlign(Align.CENTER);
    mPaint.setTextSize(mTextSize);
    mPaint.setShadowLayer(mTextShadowRadius, 0, 0, mTextShadowColor);

    final String renderText = getEllipsizedText(mPaint, title, mCachedCornerPathWidth);

    // Orient text differently depending on the angle.
    if (((rotation < 90) && (rotation > -90)) || (rotation > 270)) {
        canvas.drawTextOnPath(renderText, mCachedCornerPathReverse, 0, (2 * mTextSize), mPaint);
    } else {
        canvas.drawTextOnPath(renderText, mCachedCornerPath, 0, -mTextSize, mPaint);
    }

    mPaint.setShadowLayer(0, 0, 0, 0);
    mPaint.setColorFilter(null);
}

From source file:com.android.talkback.contextmenu.RadialMenuView.java

private void drawCorner(Canvas canvas, int width, int height, float center, int i) {
    final RadialMenuItem wedge = mRootMenu.getCorner(i);
    if (wedge == null || !wedge.isVisible()) {
        return;/*from w  ww  .  java  2s .c o m*/
    }

    final float rotation = RadialMenu.getCornerRotation(i);
    final PointF cornerLocation = RadialMenu.getCornerLocation(i);
    if (cornerLocation == null)
        return;
    final float cornerX = (cornerLocation.x * width);
    final float cornerY = (cornerLocation.y * height);
    final String title = wedge.getTitle().toString();
    final boolean selected = wedge.equals(mFocusedItem);

    // Apply the appropriate color filters.
    if (wedge.hasSubMenu()) {
        mPaint.setColorFilter(mSubMenuFilter);
    } else {
        mPaint.setColorFilter(null);
    }

    wedge.offset = rotation;

    mTempMatrix.reset();
    mTempMatrix.setRotate(rotation, center, center);
    mTempMatrix.postTranslate((cornerX - center), (cornerY - center));
    canvas.setMatrix(mTempMatrix);

    mPaint.setStyle(Style.FILL);
    mPaint.setColor(selected ? mSelectionColor : mCornerFillColor);
    mPaint.setShadowLayer(mShadowRadius, 0, 0, (selected ? mSelectionShadowColor : mTextShadowColor));
    canvas.drawPath(mCachedCornerPath, mPaint);
    mPaint.setShadowLayer(0, 0, 0, 0);

    mPaint.setStyle(Style.FILL);
    mPaint.setColor(selected ? mSelectionTextFillColor : mCornerTextFillColor);
    mPaint.setTextAlign(Align.CENTER);
    mPaint.setTextSize(mTextSize);
    mPaint.setShadowLayer(mTextShadowRadius, 0, 0, mTextShadowColor);

    final String renderText = getEllipsizedText(mPaint, title, mCachedCornerPathWidth);

    // Orient text differently depending on the angle.
    if (((rotation < 90) && (rotation > -90)) || (rotation > 270)) {
        canvas.drawTextOnPath(renderText, mCachedCornerPathReverse, 0, (2 * mTextSize), mPaint);
    } else {
        canvas.drawTextOnPath(renderText, mCachedCornerPath, 0, -mTextSize, mPaint);
    }

    mPaint.setShadowLayer(0, 0, 0, 0);
    mPaint.setColorFilter(null);
}

From source file:devlight.io.library.ArcProgressStackView.java

@Override
protected void onDraw(final Canvas canvas) {
    super.onDraw(canvas);

    // Save and rotate to start angle
    canvas.save();// ww  w .ja  va 2s  . c  om
    final float radius = mSize * 0.5F;
    canvas.rotate(mStartAngle, radius, radius);

    // Draw all of progress
    for (int i = 0; i < mModels.size(); i++) {
        final Model model = mModels.get(i);
        // Get progress for current model
        float progressFraction = mIsAnimated && !isInEditMode()
                ? (model.mLastProgress + (mAnimatedFraction * (model.getProgress() - model.mLastProgress)))
                        / MAX_PROGRESS
                : model.getProgress() / MAX_PROGRESS;
        if (i != mActionMoveModelIndex && mActionMoveModelIndex != ANIMATE_ALL_INDEX)
            progressFraction = model.getProgress() / MAX_PROGRESS;
        final float progress = progressFraction * mSweepAngle;

        // Check if model have gradient
        final boolean isGradient = model.getColors() != null;
        // Set width of progress
        mProgressPaint.setStrokeWidth(mProgressModelSize);

        // Set model arc progress
        model.mPath.reset();
        model.mPath.addArc(model.mBounds, 0.0F, progress);

        // Draw gradient progress or solid
        resetShadowLayer();
        mProgressPaint.setShader(null);
        mProgressPaint.setStyle(Paint.Style.STROKE);

        if (mIsModelBgEnabled) {
            //noinspection ResourceAsColor
            mProgressPaint.setColor(isInEditMode() ? mPreviewModelBgColor : model.getBgColor());
            canvas.drawArc(model.mBounds, 0.0F, mSweepAngle, false, mProgressPaint);
            if (!isInEditMode())
                mProgressPaint.clearShadowLayer();
        }

        // Check if gradient for draw shadow at first and then gradient progress
        if (isGradient) {
            if (!mIsModelBgEnabled) {
                canvas.drawPath(model.mPath, mProgressPaint);

                if (!isInEditMode())
                    mProgressPaint.clearShadowLayer();
            }

            mProgressPaint.setShader(model.mSweepGradient);
        } else
            mProgressPaint.setColor(model.getColor());

        // Here we draw main progress
        mProgressPaint.setAlpha(255);
        canvas.drawPath(model.mPath, mProgressPaint);

        // Preview mode
        if (isInEditMode())
            continue;

        // Get model title bounds
        mTextPaint.setTextSize(mProgressModelSize * 0.5F);
        mTextPaint.getTextBounds(model.getTitle(), 0, model.getTitle().length(), model.mTextBounds);

        // Draw title at start with offset
        final float titleHorizontalOffset = model.mTextBounds.height() * 0.5F;
        final float progressLength = (float) (Math.PI / 180.0F) * progress * model.mBounds.width() * 0.5F;
        final String title = (String) TextUtils.ellipsize(model.getTitle(), mTextPaint,
                progressLength - titleHorizontalOffset * 2, TextUtils.TruncateAt.END);
        canvas.drawTextOnPath(title, model.mPath, mIsRounded ? 0.0F : titleHorizontalOffset,
                titleHorizontalOffset, mTextPaint);

        // Get pos and tan at final path point
        model.mPathMeasure.setPath(model.mPath, false);
        model.mPathMeasure.getPosTan(model.mPathMeasure.getLength(), model.mPos, model.mTan);

        // Get title width
        final float titleWidth = model.mTextBounds.width();

        // Create model progress like : 23%
        final String percentProgress = String.format("%d%%", (int) model.getProgress());
        // Get progress text bounds
        mTextPaint.setTextSize(mProgressModelSize * 0.35f);
        mTextPaint.getTextBounds(percentProgress, 0, percentProgress.length(), model.mTextBounds);

        // Get pos tan with end point offset and check whether the rounded corners for offset
        final float progressHorizontalOffset = mIndicatorOrientation == IndicatorOrientation.VERTICAL
                ? model.mTextBounds.height() * 0.5F
                : model.mTextBounds.width() * 0.5F;
        final float indicatorProgressOffset = (mIsRounded ? progressFraction : 1.0F)
                * (-progressHorizontalOffset - titleHorizontalOffset
                        - (mIsRounded ? model.mTextBounds.height() * 2.0F : 0.0F));
        model.mPathMeasure.getPosTan(model.mPathMeasure.getLength() + indicatorProgressOffset, model.mPos,
                mIndicatorOrientation == IndicatorOrientation.VERTICAL && !mIsRounded ? new float[2]
                        : model.mTan);

        // Check if there available place for indicator
        if ((titleWidth + model.mTextBounds.height() + titleHorizontalOffset * 2.0F)
                - indicatorProgressOffset < progressLength) {
            // Get rotate indicator progress angle for progress value
            float indicatorProgressAngle = (float) (Math.atan2(model.mTan[1], model.mTan[0])
                    * (180.0F / Math.PI));
            // Get arc angle of progress indicator
            final float indicatorLengthProgressAngle = ((progressLength + indicatorProgressOffset)
                    / (model.mBounds.width() * 0.5F)) * (float) (180.0F / Math.PI);

            // Detect progress indicator position : left or right and then rotate
            if (mIndicatorOrientation == IndicatorOrientation.VERTICAL) {
                // Get X point of arc angle progress indicator
                final float x = (float) (model.mBounds.width() * 0.5F
                        * (Math.cos((indicatorLengthProgressAngle + mStartAngle) * Math.PI / 180.0F)))
                        + model.mBounds.centerX();
                indicatorProgressAngle += (x > radius) ? -90.0F : 90.0F;
            } else {
                // Get Y point of arc angle progress indicator
                final float y = (float) (model.mBounds.height() * 0.5F
                        * (Math.sin((indicatorLengthProgressAngle + mStartAngle) * Math.PI / 180.0F)))
                        + model.mBounds.centerY();
                indicatorProgressAngle += (y > radius) ? 180.0F : 0.0F;
            }

            // Draw progress value
            canvas.save();
            canvas.rotate(indicatorProgressAngle, model.mPos[0], model.mPos[1]);
            canvas.drawText(percentProgress, model.mPos[0] - model.mTextBounds.exactCenterX(),
                    model.mPos[1] - model.mTextBounds.exactCenterY(), mTextPaint);
            canvas.restore();
        }

        // Check if gradient and have rounded corners, because we must to create elevation effect
        // for start progress corner
        if ((isGradient || mIsLeveled) && mIsRounded && progress != 0) {
            model.mPathMeasure.getPosTan(0.0F, model.mPos, model.mTan);

            // Set paint for overlay rounded gradient with shadow
            setLevelShadowLayer();
            //noinspection ResourceAsColor
            mLevelPaint.setColor(isGradient ? model.getColors()[0] : model.getColor());

            // Get bounds of start pump
            final float halfSize = mProgressModelSize * 0.5F;
            final RectF arcRect = new RectF(model.mPos[0] - halfSize, model.mPos[1] - halfSize,
                    model.mPos[0] + halfSize, model.mPos[1] + halfSize + 2.0F);
            canvas.drawArc(arcRect, 0.0F, -180.0F, true, mLevelPaint);
        }
    }

    // Restore after drawing
    canvas.restore();
}