package com.kokalabs.tweening.textview;

import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.Property;
import android.view.View;

import com.kokalabs.svg.CubicBezierCurve;
import com.kokalabs.svg.SvgPath;
import com.kokalabs.svg.SvgPathTweenViaInterpolation;

public class TweeningTextView extends View {
    private static final double SCALE = 0.5;
    private static final Paint PAINT = paint();

    private static final Property<TweeningTextView, SvgPath> PATH_POINTS =
            new Property<TweeningTextView, SvgPath>(SvgPath.class, "path") {
                @Override
                public SvgPath get(TweeningTextView view) {
                    return view.path;
                }

                @Override
                public void set(TweeningTextView view, SvgPath value) {
                    view.path = value;
                    view.invalidate();
                }
            };

    private SvgPath path;

    private static Paint paint() {
        Paint p = new Paint();
        p.setAntiAlias(true);
        p.setColor(Color.BLUE);
        p.setStrokeWidth(5.0f);
        p.setStyle(Paint.Style.STROKE);
        return p;
    }

    public TweeningTextView(Context context) {
        super(context);
    }

    public TweeningTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public TweeningTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = getMeasuredWidth();
        int height = getMeasuredHeight();
        int widthWithoutPadding = width - getPaddingLeft() - getPaddingRight();
        int heightWithoutPadding = height - getPaddingTop() - getPaddingBottom();
        int maxWidth = (int) (heightWithoutPadding * SCALE);
        int maxHeight = (int) (widthWithoutPadding / SCALE);
        if (widthWithoutPadding > maxWidth) {
            width = maxWidth + getPaddingLeft() + getPaddingRight();
        } else {
            height = maxHeight + getPaddingTop() + getPaddingBottom();
        }
        setMeasuredDimension(width, height);
    }

    public ObjectAnimator animate(SvgPath start, SvgPath end) {
        return ObjectAnimator.ofObject(this, PATH_POINTS, new SvgPathTweenViaInterpolation(), start, end);
    }

    public ObjectAnimator animate(SvgPath end) {
        return animate(SvgPath.origin(), end);
    }

    private void drawTweenedText(Canvas canvas) {
        if (path == null) {
            return;
        }
        int height = getMeasuredHeight();
        int width = getMeasuredWidth();
        Adjustment adjust = new Adjustment((float) (height > width ? width : height));

        Path toDraw = new Path();
        toDraw.reset();
        for (CubicBezierCurve c : path.getPath()) {
            toDraw.moveTo(adjust.d(c.startX), adjust.d(c.startY));
            toDraw.cubicTo(
                    adjust.d(c.control1X), adjust.d(c.control1Y),
                    adjust.d(c.control2X), adjust.d(c.control2Y),
                    adjust.d(c.endX), adjust.d(c.endY));
        }
        canvas.drawPath(toDraw, PAINT);
    }

    private static class Adjustment {
        private final double minDimension;

        private Adjustment(double minDimension) {
            this.minDimension = minDimension;
        }

        private float d(double toAdjust) {
            return (float) (minDimension * toAdjust);
        }
    }
}

@@ -364,16 +364,48 @@
 rCurve;%0A
+import com.kokalabs.svg.PointD;%0A
 import c
@@ -1282,10 +1282,11 @@
 r.BL
-UE
+ACK
 );%0A 
@@ -1347,16 +1347,25 @@
 t.Style.
+FILL_AND_
 STROKE);
@@ -3241,52 +3241,242 @@
     
-for (CubicBezierCurve c : path.getPath()) %7B%0A
+toDraw.setFillType(Path.FillType.EVEN_ODD);%0A        PointD last = new PointD(-1, -1);%0A        for (CubicBezierCurve c : path.getPath()) %7B%0A            if (last.x != c.startX %7C%7C last.y != c.startY) %7B%0A                toDraw.close();%0A    
     
@@ -3534,24 +3534,38 @@
 c.startY));%0A
+            %7D%0A
             
@@ -3769,33 +3769,104 @@
 endY));%0A        
-%7D
+    last = new PointD(c.endX, c.endY);%0A        %7D%0A        toDraw.close();
 %0A        canvas.

Add fill effect to characters