Android Tutariel - 2D graphics : Canvas

Draw with Canvas

   

package app.Test;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.os.Bundle;
import android.view.View;

public class appTest extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(new GraphicsView(this));
  }
  static public class GraphicsView extends View {
    private static final String QUOTE = "This is a test. This is a demo.";
    private Path circle;
    private Paint cPaint;
    private Paint tPaint;

    public GraphicsView(Context context) {
      super(context);

      int color = Color.BLUE; 

      circle = new Path();
      circle.addCircle(150, 150, 100, Direction.CW);

      cPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
      cPaint.setStyle(Paint.Style.STROKE);
      cPaint.setColor(Color.LTGRAY);
      cPaint.setStrokeWidth(3);

      setBackgroundResource(R.drawable.icon);
    }

    @Override
    protected void onDraw(Canvas canvas) {
      canvas.drawPath(circle, cPaint);
    }
  }
}


//main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="vertical"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   android:background="@drawable/icon">
   <org.example.graphics.Graphics.GraphicsView
      android:id="@+id/graphics"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent" />
</LinearLayout>


//strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">Graphics</string>

</resources>


//colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <color name="mycolor">#7fff00ff</color> 
</resources>
Canvas Layers
package app.test;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Picture;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;


public class Test extends GraphicsActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new SampleView(this));
    }

    private static class SampleView extends View {
        private static final int LAYER_FLAGS = Canvas.MATRIX_SAVE_FLAG |
                                            Canvas.CLIP_SAVE_FLAG |
                                            Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
                                            Canvas.FULL_COLOR_LAYER_SAVE_FLAG |
                                            Canvas.CLIP_TO_LAYER_SAVE_FLAG;

        private Paint mPaint;

        public SampleView(Context context) {
            super(context);
            setFocusable(true);

            mPaint = new Paint();
            mPaint.setAntiAlias(true);
        }

        @Override protected void onDraw(Canvas canvas) {
            canvas.drawColor(Color.WHITE);

            canvas.translate(10, 10);

            canvas.saveLayerAlpha(0, 0, 200, 200, 0x88, LAYER_FLAGS);

            mPaint.setColor(Color.RED);
            canvas.drawCircle(75, 75, 75, mPaint);
            mPaint.setColor(Color.BLUE);
            canvas.drawCircle(125, 125, 75, mPaint);

            canvas.restore();
        }
    }
}



class GraphicsActivity extends Activity {
  // set to true to test Picture
  private static final boolean TEST_PICTURE = false;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
  }

  @Override
  public void setContentView(View view) {
    if (TEST_PICTURE) {
      ViewGroup vg = new PictureLayout(this);
      vg.addView(view);
      view = vg;
    }

    super.setContentView(view);
  }
}

class PictureLayout extends ViewGroup {
  private final Picture mPicture = new Picture();

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

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

  @Override
  public void addView(View child) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child);
  }

  @Override
  public void addView(View child, int index) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child, index);
  }

  @Override
  public void addView(View child, LayoutParams params) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child, params);
  }

  @Override
  public void addView(View child, int index, LayoutParams params) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child, index, params);
  }

  @Override
  protected LayoutParams generateDefaultLayoutParams() {
    return new LayoutParams(LayoutParams.MATCH_PARENT,
        LayoutParams.MATCH_PARENT);
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    final int count = getChildCount();

    int maxHeight = 0;
    int maxWidth = 0;

    for (int i = 0; i < count; i++) {
      final View child = getChildAt(i);
      if (child.getVisibility() != GONE) {
        measureChild(child, widthMeasureSpec, heightMeasureSpec);
      }
    }

    maxWidth += getPaddingLeft() + getPaddingRight();
    maxHeight += getPaddingTop() + getPaddingBottom();

    Drawable drawable = getBackground();
    if (drawable != null) {
      maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
      maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
    }

    setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec),
        resolveSize(maxHeight, heightMeasureSpec));
  }

  private void drawPict(Canvas canvas, int x, int y, int w, int h, float sx,
      float sy) {
    canvas.save();
    canvas.translate(x, y);
    canvas.clipRect(0, 0, w, h);
    canvas.scale(0.5f, 0.5f);
    canvas.scale(sx, sy, w, h);
    canvas.drawPicture(mPicture);
    canvas.restore();
  }

  @Override
  protected void dispatchDraw(Canvas canvas) {
    super.dispatchDraw(mPicture.beginRecording(getWidth(), getHeight()));
    mPicture.endRecording();

    int x = getWidth() / 2;
    int y = getHeight() / 2;

    if (false) {
      canvas.drawPicture(mPicture);
    } else {
      drawPict(canvas, 0, 0, x, y, 1, 1);
      drawPict(canvas, x, 0, x, y, -1, 1);
      drawPict(canvas, 0, y, x, y, 1, -1);
      drawPict(canvas, x, y, x, y, -1, -1);
    }
  }

  @Override
  public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
    location[0] = getLeft();
    location[1] = getTop();
    dirty.set(0, 0, getWidth(), getHeight());
    return getParent();
  }

  @Override
  protected void onLayout(boolean changed, int l, int t, int r, int b) {
    final int count = super.getChildCount();

    for (int i = 0; i < count; i++) {
      final View child = getChildAt(i);
      if (child.getVisibility() != GONE) {
        final int childLeft = getPaddingLeft();
        final int childTop = getPaddingTop();
        child.layout(childLeft, childTop,
            childLeft + child.getMeasuredWidth(),
            childTop + child.getMeasuredHeight());

      }
    }
  }
}
Translate Canvas
package app.test;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Picture;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;

public class Test extends GraphicsActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new SampleView(this));
    }

    private static class SampleView extends View {
        private Paint   mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        private Matrix  mMatrix = new Matrix();
        private Paint.FontMetrics mFontMetrics;

        private void doDraw(Canvas canvas, float src[], float dst[]) {
            canvas.save();
            mMatrix.setPolyToPoly(src, 0, dst, 0, src.length >> 1);
            canvas.concat(mMatrix);

            mPaint.setColor(Color.GRAY);
            mPaint.setStyle(Paint.Style.STROKE);
            canvas.drawRect(0, 0, 64, 64, mPaint);
            canvas.drawLine(0, 0, 64, 64, mPaint);
            canvas.drawLine(0, 64, 64, 0, mPaint);

            mPaint.setColor(Color.RED);
            mPaint.setStyle(Paint.Style.FILL);
            // how to draw the text center on our square
            // centering in X is easy... use alignment (and X at midpoint)
            float x = 64/2;
            // centering in Y, we need to measure ascent/descent first
            float y = 64/2 - (mFontMetrics.ascent + mFontMetrics.descent)/2;
            canvas.drawText(src.length/2 + "", x, y, mPaint);

            canvas.restore();
        }

        public SampleView(Context context) {
            super(context);

            // for when the style is STROKE
            mPaint.setStrokeWidth(4);
            // for when we draw text
            mPaint.setTextSize(40);
            mPaint.setTextAlign(Paint.Align.CENTER);
            mFontMetrics = mPaint.getFontMetrics();
        }

        @Override
        protected void onDraw(Canvas canvas) {
            canvas.drawColor(Color.WHITE);

            canvas.save();
            canvas.translate(10, 10);
            // translate (1 point)
            doDraw(canvas, new float[] { 0, 0 }, new float[] { 5, 5 });
            canvas.restore();

            canvas.save();
            canvas.translate(160, 10);
            // rotate/uniform-scale (2 points)
            doDraw(canvas, new float[] { 32, 32, 64, 32 },
                           new float[] { 32, 32, 64, 48 });
            canvas.restore();

            canvas.save();
            canvas.translate(10, 110);
            // rotate/skew (3 points)
            doDraw(canvas, new float[] { 0, 0, 64, 0, 0, 64 },
                           new float[] { 0, 0, 96, 0, 24, 64 });
            canvas.restore();

            canvas.save();
            canvas.translate(160, 110);
            // perspective (4 points)
            doDraw(canvas, new float[] { 0, 0, 64, 0, 64, 64, 0, 64 },
                           new float[] { 0, 0, 96, 0, 64, 96, 0, 64 });
            canvas.restore();
        }
    }
}

class GraphicsActivity extends Activity {
  // set to true to test Picture
  private static final boolean TEST_PICTURE = false;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
  }

  @Override
  public void setContentView(View view) {
    if (TEST_PICTURE) {
      ViewGroup vg = new PictureLayout(this);
      vg.addView(view);
      view = vg;
    }

    super.setContentView(view);
  }
}

class PictureLayout extends ViewGroup {
  private final Picture mPicture = new Picture();

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

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

  @Override
  public void addView(View child) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child);
  }

  @Override
  public void addView(View child, int index) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child, index);
  }

  @Override
  public void addView(View child, LayoutParams params) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child, params);
  }

  @Override
  public void addView(View child, int index, LayoutParams params) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child, index, params);
  }

  @Override
  protected LayoutParams generateDefaultLayoutParams() {
    return new LayoutParams(LayoutParams.MATCH_PARENT,
        LayoutParams.MATCH_PARENT);
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    final int count = getChildCount();

    int maxHeight = 0;
    int maxWidth = 0;

    for (int i = 0; i < count; i++) {
      final View child = getChildAt(i);
      if (child.getVisibility() != GONE) {
        measureChild(child, widthMeasureSpec, heightMeasureSpec);
      }
    }

    maxWidth += getPaddingLeft() + getPaddingRight();
    maxHeight += getPaddingTop() + getPaddingBottom();

    Drawable drawable = getBackground();
    if (drawable != null) {
      maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
      maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
    }

    setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec),
        resolveSize(maxHeight, heightMeasureSpec));
  }

  private void drawPict(Canvas canvas, int x, int y, int w, int h, float sx,
      float sy) {
    canvas.save();
    canvas.translate(x, y);
    canvas.clipRect(0, 0, w, h);
    canvas.scale(0.5f, 0.5f);
    canvas.scale(sx, sy, w, h);
    canvas.drawPicture(mPicture);
    canvas.restore();
  }

  @Override
  protected void dispatchDraw(Canvas canvas) {
    super.dispatchDraw(mPicture.beginRecording(getWidth(), getHeight()));
    mPicture.endRecording();

    int x = getWidth() / 2;
    int y = getHeight() / 2;

    if (false) {
      canvas.drawPicture(mPicture);
    } else {
      drawPict(canvas, 0, 0, x, y, 1, 1);
      drawPict(canvas, x, 0, x, y, -1, 1);
      drawPict(canvas, 0, y, x, y, 1, -1);
      drawPict(canvas, x, y, x, y, -1, -1);
    }
  }

  @Override
  public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
    location[0] = getLeft();
    location[1] = getTop();
    dirty.set(0, 0, getWidth(), getHeight());
    return getParent();
  }

  @Override
  protected void onLayout(boolean changed, int l, int t, int r, int b) {
    final int count = super.getChildCount();

    for (int i = 0; i < count; i++) {
      final View child = getChildAt(i);
      if (child.getVisibility() != GONE) {
        final int childLeft = getPaddingLeft();
        final int childTop = getPaddingTop();
        child.layout(childLeft, childTop,
            childLeft + child.getMeasuredWidth(),
            childTop + child.getMeasuredHeight());

      }
    }
  }
}
Sweep
package app.test;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Picture;
import android.graphics.Rect;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.LinearLayout.LayoutParams;

public class Test extends GraphicsActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(new SampleView(this));
  }

  private static class SampleView extends View {
    private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private float mRotate;
    private Matrix mMatrix = new Matrix();
    private Shader mShader;
    private boolean mDoTiming;

    public SampleView(Context context) {
      super(context);
      setFocusable(true);
      setFocusableInTouchMode(true);

      float x = 160;
      float y = 100;
      mShader = new SweepGradient(x, y, new int[] { Color.GREEN,
          Color.RED, Color.BLUE, Color.GREEN }, null);
      mPaint.setShader(mShader);
    }

    @Override
    protected void onDraw(Canvas canvas) {
      Paint paint = mPaint;
      float x = 160;
      float y = 100;

      canvas.drawColor(Color.WHITE);

      mMatrix.setRotate(mRotate, x, y);
      mShader.setLocalMatrix(mMatrix);
      mRotate += 3;
      if (mRotate >= 360) {
        mRotate = 0;
      }
      invalidate();

      if (mDoTiming) {
        long now = System.currentTimeMillis();
        for (int i = 0; i < 20; i++) {
          canvas.drawCircle(x, y, 80, paint);
        }
        now = System.currentTimeMillis() - now;
        android.util.Log.d("skia", "sweep ms = " + (now / 20.));
      } else {
        canvas.drawCircle(x, y, 80, paint);
      }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
      switch (keyCode) {
      case KeyEvent.KEYCODE_D:
        mPaint.setDither(!mPaint.isDither());
        invalidate();
        return true;
      case KeyEvent.KEYCODE_T:
        mDoTiming = !mDoTiming;
        invalidate();
        return true;
      }
      return super.onKeyDown(keyCode, event);
    }
  }
}

class GraphicsActivity extends Activity {
  // set to true to test Picture
  private static final boolean TEST_PICTURE = false;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
  }

  @Override
  public void setContentView(View view) {
    if (TEST_PICTURE) {
      ViewGroup vg = new PictureLayout(this);
      vg.addView(view);
      view = vg;
    }

    super.setContentView(view);
  }
}

class PictureLayout extends ViewGroup {
  private final Picture mPicture = new Picture();

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

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

  @Override
  public void addView(View child) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child);
  }

  @Override
  public void addView(View child, int index) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child, index);
  }

  @Override
  public void addView(View child, LayoutParams params) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child, params);
  }

  @Override
  public void addView(View child, int index, LayoutParams params) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child, index, params);
  }

  @Override
  protected LayoutParams generateDefaultLayoutParams() {
    return new LayoutParams(LayoutParams.MATCH_PARENT,
        LayoutParams.MATCH_PARENT);
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    final int count = getChildCount();

    int maxHeight = 0;
    int maxWidth = 0;

    for (int i = 0; i < count; i++) {
      final View child = getChildAt(i);
      if (child.getVisibility() != GONE) {
        measureChild(child, widthMeasureSpec, heightMeasureSpec);
      }
    }

    maxWidth += getPaddingLeft() + getPaddingRight();
    maxHeight += getPaddingTop() + getPaddingBottom();

    Drawable drawable = getBackground();
    if (drawable != null) {
      maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
      maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
    }

    setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec),
        resolveSize(maxHeight, heightMeasureSpec));
  }

  private void drawPict(Canvas canvas, int x, int y, int w, int h, float sx,
      float sy) {
    canvas.save();
    canvas.translate(x, y);
    canvas.clipRect(0, 0, w, h);
    canvas.scale(0.5f, 0.5f);
    canvas.scale(sx, sy, w, h);
    canvas.drawPicture(mPicture);
    canvas.restore();
  }

  @Override
  protected void dispatchDraw(Canvas canvas) {
    super.dispatchDraw(mPicture.beginRecording(getWidth(), getHeight()));
    mPicture.endRecording();

    int x = getWidth() / 2;
    int y = getHeight() / 2;

    if (false) {
      canvas.drawPicture(mPicture);
    } else {
      drawPict(canvas, 0, 0, x, y, 1, 1);
      drawPict(canvas, x, 0, x, y, -1, 1);
      drawPict(canvas, 0, y, x, y, 1, -1);
      drawPict(canvas, x, y, x, y, -1, -1);
    }
  }

  @Override
  public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
    location[0] = getLeft();
    location[1] = getTop();
    dirty.set(0, 0, getWidth(), getHeight());
    return getParent();
  }

  @Override
  protected void onLayout(boolean changed, int l, int t, int r, int b) {
    final int count = super.getChildCount();

    for (int i = 0; i < count; i++) {
      final View child = getChildAt(i);
      if (child.getVisibility() != GONE) {
        final int childLeft = getPaddingLeft();
        final int childTop = getPaddingTop();
        child.layout(childLeft, childTop,
            childLeft + child.getMeasuredWidth(),
            childTop + child.getMeasuredHeight());

      }
    }
  }
}
Vertices
package app.test;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Picture;
import android.graphics.Rect;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;

public class Test extends GraphicsActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(new SampleView(this));
  }

  private static class SampleView extends View {
    private final Paint mPaint = new Paint();
    private final float[] mVerts = new float[10];
    private final float[] mTexs = new float[10];
    private final short[] mIndices = { 0, 1, 2, 3, 4, 1 };

    private final Matrix mMatrix = new Matrix();
    private final Matrix mInverse = new Matrix();

    private static void setXY(float[] array, int index, float x, float y) {
      array[index * 2 + 0] = x;
      array[index * 2 + 1] = y;
    }

    public SampleView(Context context) {
      super(context);
      setFocusable(true);

      Bitmap bm = BitmapFactory.decodeResource(getResources(),
          R.drawable.icon);
      Shader s = new BitmapShader(bm, Shader.TileMode.CLAMP,
          Shader.TileMode.CLAMP);
      mPaint.setShader(s);

      float w = bm.getWidth();
      float h = bm.getHeight();
      // construct our mesh
      setXY(mTexs, 0, w / 2, h / 2);
      setXY(mTexs, 1, 0, 0);
      setXY(mTexs, 2, w, 0);
      setXY(mTexs, 3, w, h);
      setXY(mTexs, 4, 0, h);

      setXY(mVerts, 0, w / 2, h / 2);
      setXY(mVerts, 1, 0, 0);
      setXY(mVerts, 2, w, 0);
      setXY(mVerts, 3, w, h);
      setXY(mVerts, 4, 0, h);

      mMatrix.setScale(0.8f, 0.8f);
      mMatrix.preTranslate(20, 20);
      mMatrix.invert(mInverse);
    }

    @Override
    protected void onDraw(Canvas canvas) {
      canvas.drawColor(0xFFCCCCCC);
      canvas.save();
      canvas.concat(mMatrix);

      canvas.drawVertices(Canvas.VertexMode.TRIANGLE_FAN, 10, mVerts, 0,
          mTexs, 0, null, 0, null, 0, 0, mPaint);

      canvas.translate(0, 240);
      canvas.drawVertices(Canvas.VertexMode.TRIANGLE_FAN, 10, mVerts, 0,
          mTexs, 0, null, 0, mIndices, 0, 6, mPaint);

      canvas.restore();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
      float[] pt = { event.getX(), event.getY() };
      mInverse.mapPoints(pt);
      setXY(mVerts, 0, pt[0], pt[1]);
      invalidate();
      return true;
    }

  }
}

class GraphicsActivity extends Activity {
  // set to true to test Picture
  private static final boolean TEST_PICTURE = false;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
  }

  @Override
  public void setContentView(View view) {
    if (TEST_PICTURE) {
      ViewGroup vg = new PictureLayout(this);
      vg.addView(view);
      view = vg;
    }

    super.setContentView(view);
  }
}

class PictureLayout extends ViewGroup {
  private final Picture mPicture = new Picture();

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

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

  @Override
  public void addView(View child) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child);
  }

  @Override
  public void addView(View child, int index) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child, index);
  }

  @Override
  public void addView(View child, LayoutParams params) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child, params);
  }

  @Override
  public void addView(View child, int index, LayoutParams params) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child, index, params);
  }

  @Override
  protected LayoutParams generateDefaultLayoutParams() {
    return new LayoutParams(LayoutParams.MATCH_PARENT,
        LayoutParams.MATCH_PARENT);
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    final int count = getChildCount();

    int maxHeight = 0;
    int maxWidth = 0;

    for (int i = 0; i < count; i++) {
      final View child = getChildAt(i);
      if (child.getVisibility() != GONE) {
        measureChild(child, widthMeasureSpec, heightMeasureSpec);
      }
    }

    maxWidth += getPaddingLeft() + getPaddingRight();
    maxHeight += getPaddingTop() + getPaddingBottom();

    Drawable drawable = getBackground();
    if (drawable != null) {
      maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
      maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
    }

    setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec),
        resolveSize(maxHeight, heightMeasureSpec));
  }

  private void drawPict(Canvas canvas, int x, int y, int w, int h, float sx,
      float sy) {
    canvas.save();
    canvas.translate(x, y);
    canvas.clipRect(0, 0, w, h);
    canvas.scale(0.5f, 0.5f);
    canvas.scale(sx, sy, w, h);
    canvas.drawPicture(mPicture);
    canvas.restore();
  }

  @Override
  protected void dispatchDraw(Canvas canvas) {
    super.dispatchDraw(mPicture.beginRecording(getWidth(), getHeight()));
    mPicture.endRecording();

    int x = getWidth() / 2;
    int y = getHeight() / 2;

    if (false) {
      canvas.drawPicture(mPicture);
    } else {
      drawPict(canvas, 0, 0, x, y, 1, 1);
      drawPict(canvas, x, 0, x, y, -1, 1);
      drawPict(canvas, 0, y, x, y, 1, -1);
      drawPict(canvas, x, y, x, y, -1, -1);
    }
  }

  @Override
  public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
    location[0] = getLeft();
    location[1] = getTop();
    dirty.set(0, 0, getWidth(), getHeight());
    return getParent();
  }

  @Override
  protected void onLayout(boolean changed, int l, int t, int r, int b) {
    final int count = super.getChildCount();

    for (int i = 0; i < count; i++) {
      final View child = getChildAt(i);
      if (child.getVisibility() != GONE) {
        final int childLeft = getPaddingLeft();
        final int childTop = getPaddingTop();
        child.layout(childLeft, childTop,
            childLeft + child.getMeasuredWidth(),
            childTop + child.getMeasuredHeight());

      }
    }
  }
}

Scale To Fit

package app.test;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Picture;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;

public class Test extends GraphicsActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(new SampleView(this));
  }

  private static class SampleView extends View {
    private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private final Paint mHairPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private final Paint mLabelPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private final Matrix mMatrix = new Matrix();
    private final RectF mSrcR = new RectF();

    private static final Matrix.ScaleToFit[] sFits = new Matrix.ScaleToFit[] {
        Matrix.ScaleToFit.FILL, Matrix.ScaleToFit.START,
        Matrix.ScaleToFit.CENTER, Matrix.ScaleToFit.END };

    private static final String[] sFitLabels = new String[] { "FILL",
        "START", "CENTER", "END" };

    private static final int[] sSrcData = new int[] { 80, 40, Color.RED,
        40, 80, Color.GREEN, 30, 30, Color.BLUE, 80, 80, Color.BLACK };
    private static final int N = 4;

    private static final int WIDTH = 52;
    private static final int HEIGHT = 52;
    private final RectF mDstR = new RectF(0, 0, WIDTH, HEIGHT);

    public SampleView(Context context) {
      super(context);

      mHairPaint.setStyle(Paint.Style.STROKE);
      mLabelPaint.setTextSize(16);
    }

    private void setSrcR(int index) {
      int w = sSrcData[index * 3 + 0];
      int h = sSrcData[index * 3 + 1];
      mSrcR.set(0, 0, w, h);
    }

    private void drawSrcR(Canvas canvas, int index) {
      mPaint.setColor(sSrcData[index * 3 + 2]);
      canvas.drawOval(mSrcR, mPaint);
    }

    private void drawFit(Canvas canvas, int index, Matrix.ScaleToFit stf) {
      canvas.save();

      setSrcR(index);
      mMatrix.setRectToRect(mSrcR, mDstR, stf);
      canvas.concat(mMatrix);
      drawSrcR(canvas, index);

      canvas.restore();

      canvas.drawRect(mDstR, mHairPaint);
    }

    @Override
    protected void onDraw(Canvas canvas) {
      canvas.drawColor(Color.WHITE);

      canvas.translate(10, 10);

      canvas.save();
      for (int i = 0; i < N; i++) {
        setSrcR(i);
        drawSrcR(canvas, i);
        canvas.translate(mSrcR.width() + 15, 0);
      }
      canvas.restore();

      canvas.translate(0, 100);
      for (int j = 0; j < sFits.length; j++) {
        canvas.save();
        for (int i = 0; i < N; i++) {
          drawFit(canvas, i, sFits[j]);
          canvas.translate(mDstR.width() + 8, 0);
        }
        canvas.drawText(sFitLabels[j], 0, HEIGHT * 2 / 3, mLabelPaint);
        canvas.restore();
        canvas.translate(0, 80);
      }
    }
  }
}

class GraphicsActivity extends Activity {
  // set to true to test Picture
  private static final boolean TEST_PICTURE = false;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
  }

  @Override
  public void setContentView(View view) {
    if (TEST_PICTURE) {
      ViewGroup vg = new PictureLayout(this);
      vg.addView(view);
      view = vg;
    }

    super.setContentView(view);
  }
}

class PictureLayout extends ViewGroup {
  private final Picture mPicture = new Picture();

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

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

  @Override
  public void addView(View child) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child);
  }

  @Override
  public void addView(View child, int index) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child, index);
  }

  @Override
  public void addView(View child, LayoutParams params) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child, params);
  }

  @Override
  public void addView(View child, int index, LayoutParams params) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child, index, params);
  }

  @Override
  protected LayoutParams generateDefaultLayoutParams() {
    return new LayoutParams(LayoutParams.MATCH_PARENT,
        LayoutParams.MATCH_PARENT);
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    final int count = getChildCount();

    int maxHeight = 0;
    int maxWidth = 0;

    for (int i = 0; i < count; i++) {
      final View child = getChildAt(i);
      if (child.getVisibility() != GONE) {
        measureChild(child, widthMeasureSpec, heightMeasureSpec);
      }
    }

    maxWidth += getPaddingLeft() + getPaddingRight();
    maxHeight += getPaddingTop() + getPaddingBottom();

    Drawable drawable = getBackground();
    if (drawable != null) {
      maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
      maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
    }

    setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec),
        resolveSize(maxHeight, heightMeasureSpec));
  }

  private void drawPict(Canvas canvas, int x, int y, int w, int h, float sx,
      float sy) {
    canvas.save();
    canvas.translate(x, y);
    canvas.clipRect(0, 0, w, h);
    canvas.scale(0.5f, 0.5f);
    canvas.scale(sx, sy, w, h);
    canvas.drawPicture(mPicture);
    canvas.restore();
  }

  @Override
  protected void dispatchDraw(Canvas canvas) {
    super.dispatchDraw(mPicture.beginRecording(getWidth(), getHeight()));
    mPicture.endRecording();

    int x = getWidth() / 2;
    int y = getHeight() / 2;

    if (false) {
      canvas.drawPicture(mPicture);
    } else {
      drawPict(canvas, 0, 0, x, y, 1, 1);
      drawPict(canvas, x, 0, x, y, -1, 1);
      drawPict(canvas, 0, y, x, y, 1, -1);
      drawPict(canvas, x, y, x, y, -1, -1);
    }
  }

  @Override
  public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
    location[0] = getLeft();
    location[1] = getTop();
    dirty.set(0, 0, getWidth(), getHeight());
    return getParent();
  }

  @Override
  protected void onLayout(boolean changed, int l, int t, int r, int b) {
    final int count = super.getChildCount();

    for (int i = 0; i < count; i++) {
      final View child = getChildAt(i);
      if (child.getVisibility() != GONE) {
        final int childLeft = getPaddingLeft();
        final int childTop = getPaddingTop();
        child.layout(childLeft, childTop,
            childLeft + child.getMeasuredWidth(),
            childTop + child.getMeasuredHeight());

      }
    }
  }
}

Draw Pint

    


import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.drawable.Drawable;

public class Pint{
  private Drawable bgFull, bgEmpty, bgFront;
  private Bitmap foam;
  private static final float WIDTH = 320;
  private static final float HEIGHT = 480;
  private static final float TOTAL = WIDTH*HEIGHT - 50*320;
  private float currentVolume = 0;
  
  float leftY=480, rightY=480;
  float foamHeight;
  
  public Pint(Drawable bgFull, Drawable bgEmpty, Drawable bgFront, Bitmap foam){
    this.bgEmpty = bgEmpty;
    this.bgEmpty.setBounds(0, 0, bgEmpty.getIntrinsicWidth(), bgEmpty.getIntrinsicHeight());
    this.bgFull = bgFull;
    this.bgFull.setBounds(0, 0, bgFull.getIntrinsicWidth(), bgFull.getIntrinsicHeight());
    this.bgFront = bgFront;
    this.bgFront.setBounds(0, 0, bgFront.getIntrinsicWidth(), bgFront.getIntrinsicHeight());
    this.foam = foam;
    foamHeight = foam.getHeight()/2;
  }
  
  private float angle  = 0f;
  private boolean full = false;
  
  public void setAngle(float angle) {
    this.angle = angle;
  }
  
  public float getCurrentVolume() {
    return currentVolume;
  }
  
  public void setCurrentVolume(float currentVolume) {
    this.currentVolume = currentVolume;
}
  
  public void draw(Canvas canvas){

    bgEmpty.draw(canvas);
    canvas.save();
  
    float emptyHeight = 0;
    if(!full){
      currentVolume += (10 * 320);
      if(currentVolume > TOTAL){
        full = true;
      }
    }

    emptyHeight = (float) (Math.tan(Math.toRadians(angle)) * WIDTH);
    
    float adjustedHeight = currentVolume / WIDTH; //normal height
    adjustedHeight = adjustedHeight <= 0? 2f : adjustedHeight;

    leftY = Math.max(-1000, HEIGHT - ( adjustedHeight + emptyHeight));
    rightY = Math.max(-1000, HEIGHT - (adjustedHeight - emptyHeight));
    
    if(currentVolume > WIDTH){
      Path p = new Path();
      p.moveTo(0, HEIGHT); //lower left
      p.lineTo(WIDTH, HEIGHT);
      p.lineTo(WIDTH, rightY);
      p.lineTo(0, leftY);
      canvas.clipPath(p);
      bgFull.draw(canvas);
      canvas.restore();    

      canvas.drawBitmapMesh(
          foam, 1, 1, new float[]{
              0, leftY-foamHeight, 320, rightY-foamHeight,
              0, leftY+foamHeight, 320, rightY+foamHeight,}, 0, null, 0, null);

    }
        
    if(leftY < 5 || rightY < 5){
      currentVolume *= 0.98;// -= (2000f);
      currentVolume -= 200f;
    }

    bgFront.draw(canvas);
  }
  
}

Class for the scribble/memo pad

    
//package com.neugent.aethervoice.ui;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.view.MotionEvent;
import android.view.View;

/**
 * Class for the scribble/memo pad
 * 
 * @author Amando Jose Quinto II
 * 
 */
public class Scribble extends View {
  private static final int INVALID_POINTER_ID = -1;
  

  /** The paint used in drawing the path. **/
  private final Paint mPaint;

  /** The canvas for the path to be drawn. **/
  private static Canvas mCanvas;

  /** The path 1 to be drawn. **/
  private final Path mPath1;
  
  /** The path 2 to be drawn. **/
  private final Path mPath2;

  /** The paint used by the bitmap **/
  private final Paint mBitmapPaint;

  /** Bitmap for the screen **/
  private final Bitmap mBitmap = Bitmap.createBitmap(480, 390,
      Bitmap.Config.ARGB_8888);

  /** The flag for erasing the canvas. **/
  private boolean mErase = false;

  /** The starting point for x-coordinate. **/
  private float mX1;

  /** The starting point for y-coordinate. **/
  private float mY1;
  
  /** The starting point for x-coordinate. **/
  private float mX2;

  /** The starting point for y-coordinate. **/
  private float mY2;

  /** The tolerance of the finger movement. **/
  private static final float TOUCH_TOLERANCE = 4;
  
    private int mActivePointerId = INVALID_POINTER_ID;

  /**
   * Instantiate the Scribble.
   * 
   * @param context
   *            The application context
   */
  public Scribble(final Context context) {
    super(context);

    Scribble.mCanvas = new Canvas(mBitmap);
    mBitmapPaint = new Paint(Paint.DITHER_FLAG);
    
    mPath1 = new Path();
    mPath2 = new Path();

    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setDither(true);
    mPaint.setColor(Color.RED);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeJoin(Paint.Join.ROUND);
    mPaint.setStrokeCap(Paint.Cap.ROUND);
    mPaint.setStrokeWidth(6);

  }

  @Override
  protected void onSizeChanged(final int w, final int h, final int oldw,
      final int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
  }

  /**
   * Draw/Erases the path determined by the user
   * 
   * @see android.view.View#onDraw(android.graphics.Canvas)
   */
  @Override
  protected void onDraw(final Canvas canvas) {
    if (mErase) {
      final Paint p = new Paint();
      p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
      Scribble.mCanvas.drawRect(0, 0, getWidth(), getHeight(), p);
      mErase = false;
    } else {
      canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);

      canvas.drawPath(mPath1, mPaint);
      canvas.drawPath(mPath2, mPaint);
    }
  }

  /**
   * 
   */
  public void eraseAll() {
    mErase = true;
    invalidate();
  }

  /**
   * @param x
   *            the x-coordinate
   * @param y
   *            the y-coordinate
   * 
   * @see android.view.View#onTouchEvent(MotionEvent)
   * @see android.view.MotionEvent#ACTION_DOWN
   */
  private void touch_start(final float x, final float y, final int index) {
    switch(index){
    case 0:
      mPath1.reset();
      mPath1.moveTo(x, y);
      mX1 = x;
      mY1 = y;
      break;
    case 1:
      mPath2.reset();
      mPath2.moveTo(x, y);
      mX2 = x;
      mY2 = y;
      break;
    }
  }

  /**
   * Draws the path.
   * 
   * @param x
   *            the x-coordinate
   * @param y
   *            the y-coordinate
   * 
   * @see android.view.View#onTouchEvent(MotionEvent)
   * @see android.view.MotionEvent#ACTION_MOVE
   */
  private void touch_move(final float x, final float y, int pointerIndex) {
    switch(pointerIndex){
    case 0:
      if (Math.abs(x - mX1) >= Scribble.TOUCH_TOLERANCE || Math.abs(y - mY1) >= Scribble.TOUCH_TOLERANCE) {
        mPath1.quadTo(mX1, mY1, (x + mX1) / 2, (y + mY1) / 2);
        mX1 = x;
        mY1 = y;
      }
      break;
    case 1:
      if (Math.abs(x - mX2) >= Scribble.TOUCH_TOLERANCE || Math.abs(y - mY2) >= Scribble.TOUCH_TOLERANCE) {
        mPath2.quadTo(mX2, mY2, (x + mX2) / 2, (y + mY2) / 2);
        mX2 = x;
        mY2 = y;
      }
      break;
    }
  }

  /**
   * Finishes the path.
   * 
   * @see android.view.View#onTouchEvent(MotionEvent)
   * @see android.view.MotionEvent#ACTION_UP
   */
  private void touch_up(int index) {
    switch(index){
    case 0:
      mPath1.lineTo(mX1, mY1);
      // commit the path to our offscreen
      Scribble.mCanvas.drawPath(mPath1, mPaint);
      // kill this so we don't double draw
      mPath1.reset();
      break;
    case 1:
      mPath2.lineTo(mX2, mY2);
      // commit the path to our offscreen
      Scribble.mCanvas.drawPath(mPath2, mPaint);
      // kill this so we don't double draw
      mPath2.reset();
      break;
    }
    
  }

  @Override
  public boolean onTouchEvent(final MotionEvent event) {
    final int action = event.getAction();

    switch (action & MotionEvent.ACTION_MASK) {
    case MotionEvent.ACTION_DOWN:{
      final float x = event.getX();
      final float y = event.getY();
      
          // Save the ID of this pointer
          mActivePointerId = event.getPointerId(0);
          
      touch_start(x, y, 0);
      invalidate();
      break;
    } case MotionEvent.ACTION_POINTER_DOWN:{
      final int pointerIndex2 = event.findPointerIndex(event.getPointerCount() - 1);

          final float x = event.getX(pointerIndex2);
          final float y = event.getY(pointerIndex2);
      touch_start(x, y, 1);
      invalidate();
      break;
    } case MotionEvent.ACTION_MOVE:{
      final int count = event.getPointerCount();
      // Find the index of the active pointer and fetch its position
          final int pointerIndex = event.findPointerIndex(mActivePointerId);
          final int pointerIndex2 = event.findPointerIndex(count - 1);

          final float x = event.getX(pointerIndex);
          final float y = event.getY(pointerIndex);
          
          touch_move(x, y, pointerIndex);
                    
          if(count > 1 && pointerIndex2 != pointerIndex){
            final float x2 = event.getX(pointerIndex2);
            final float y2= event.getY(pointerIndex2);
            
            touch_move(x2, y2, pointerIndex2);
          }
          
      invalidate();
      break;
    } case MotionEvent.ACTION_UP:
      mActivePointerId = INVALID_POINTER_ID;
//      System.out.println("AetherVoice ++++++++++++++++++++++++++ ACTION_UP");
      if(event.getPointerCount() < 2)
        touch_up(0);
      break;
      
    case MotionEvent.ACTION_CANCEL:
      mActivePointerId = INVALID_POINTER_ID;
      
//      System.out.println("AetherVoice +++++++++++++++++ ACTION_CANCEL");
      break;
    case MotionEvent.ACTION_POINTER_UP:
//      System.out.println("AetherVoice ++++++++++++++++++ ACTION_POINTER_UP");
      
      final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
      final int pointerId = event.getPointerId(pointerIndex);
      if (pointerId == mActivePointerId) {
            // This was our active pointer going up. Choose a new
            // active pointer and adjust accordingly.
            final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
            mActivePointerId = event.getPointerId(newPointerIndex);
            touch_up(0);
            mPath1.moveTo(mX2, mY2);
            mX1 = mX2;
            mY1 = mY2;
      }
//      System.out.println("AetherVoice ++++++++++++++++++++++ mActivePointerId "+mActivePointerId);
      touch_up(1);
      break;
    }
    //invalidate();
    return true;
  }

}
Bezier interpolate
//package org.ametro.util;

import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;

 class Algorithms {

    private final static int LEFT = 1;
    private final static int RIGHT = 2;
    private final static int TOP = 4;
    private final static int BOTTOM = 8;

    public static class Solve2x2 {
        float __determinant = 0;

        public PointF solve(float _a11, float _a12, float _a21, float _a22, float _b1, float _b2, float zeroTolerance, boolean _resolve) {
            if (!_resolve) {
                __determinant = _a11 * _a22 - _a12 * _a21;
            }

            // exercise - dispatch an event if the determinant is near zero
            if (__determinant > zeroTolerance) {
                float x = (_a22 * _b1 - _a12 * _b2) / __determinant;
                float y = (_a11 * _b2 - _a21 * _b1) / __determinant;
                return new PointF(x, y);
            }
            return null;
        }

    }

    public static class QBezierControls {
        public final float x0;
        public final float y0;
        public final float x1;
        public final float y1;

        public QBezierControls(float newX0, float newY0, float newX1, float newY1) {
            super();
            x0 = newX0;
            y0 = newY0;
            x1 = newX1;
            y1 = newY1;
        }

    }

    public static float calculateDistance(Point p0, Point p1) {
        int dx = p0.x - p1.x;
        int dy = p0.y - p1.y;
        return (float) Math.sqrt(dx * dx + dy * dy);
    }

    public static float calculateAngle(float x0, float y0, float x, float y) {
        float angle = (float) (Math.atan((y - y0) / (x - x0)) / Math.PI * 180);
        float dx = x - x0;
        float dy = y - y0;
        if (angle > 0) {
            if (dx < 0 && dy < 0) {
                angle += 180;
            }
        } else if (angle < 0) {
            if (dx < 0 && dy > 0) {
                angle += 180;
            } else {
                angle += 360;
            }
        } else {
            if (dx < 0) {
                angle = 180;
            }
        }
        return angle;
    }

    public static PointF interpolateQuadBezier(Point p0, Point p1, Point p2) {
        // compute t-value using chord-length parameterization
        float dx = p1.x - p0.x;
        float dy = p1.y - p0.y;
        float d1 = (float) Math.sqrt(dx * dx + dy * dy);
        float d = d1;

        dx = p2.x - p1.x;
        dy = p2.y - p1.y;
        d += (float) Math.sqrt(dx * dx + dy * dy);

        float t = d1 / d;
        float t1 = 1.0f - t;
        float tSq = t * t;
        float denom = 2.0f * t * t1;

        PointF p = new PointF();
        p.x = (p1.x - t1 * t1 * p0.x - tSq * p2.x) / denom;
        p.y = (p1.y - t1 * t1 * p0.y - tSq * p2.y) / denom;

        return p;
    }

    public static QBezierControls interpolateCubeBezierSmooth(Point p0, Point p1, Point p2, Point p3, float smoothFactor) {
        // Assume we need to calculate the control
        // points between (x1,y1) and (x2,y2).
        // Then x0,y0 - the previous vertex,
        //      x3,y3 - the next one.

        float x0 = p0.x;
        float y0 = p0.y;
        float x1 = p1.x;
        float y1 = p1.y;
        float x2 = p2.x;
        float y2 = p2.y;
        float x3 = p3.x;
        float y3 = p3.y;

        float xc1 = (x0 + x1) / 2.0f;
        float yc1 = (y0 + y1) / 2.0f;
        float xc2 = (x1 + x2) / 2.0f;
        float yc2 = (y1 + y2) / 2.0f;
        float xc3 = (x2 + x3) / 2.0f;
        float yc3 = (y2 + y3) / 2.0f;

        float len1 = (float) Math.sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
        float len2 = (float) Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
        float len3 = (float) Math.sqrt((x3 - x2) * (x3 - x2) + (y3 - y2) * (y3 - y2));

        float k1 = len1 / (len1 + len2);
        float k2 = len2 / (len2 + len3);

        float xm1 = xc1 + (xc2 - xc1) * k1;
        float ym1 = yc1 + (yc2 - yc1) * k1;
        float xm2 = xc2 + (xc3 - xc2) * k2;
        float ym2 = yc2 + (yc3 - yc2) * k2;

        float ctrl1_x = xm1 + (xc2 - xm1) * smoothFactor + x1 - xm1;
        float ctrl1_y = ym1 + (yc2 - ym1) * smoothFactor + y1 - ym1;
        float ctrl2_x = xm2 + (xc2 - xm2) * smoothFactor + x2 - xm2;
        float ctrl2_y = ym2 + (yc2 - ym2) * smoothFactor + y2 - ym2;
        return new QBezierControls(ctrl1_x, ctrl1_y, ctrl2_x, ctrl2_y);
    }

    public static int vcode(Rect r, Point p) {
        return (((p.x < r.left) ? LEFT : 0) +
                ((p.x > r.right) ? RIGHT : 0) +
                ((p.y < r.top) ? TOP : 0) +
                ((p.y > r.bottom) ? BOTTOM : 0));
    }

    public static boolean clipCohenSutherland(Rect r, Point a, Point b) {
        a = new Point(a);
        b = new Point(b);
        int code_a, code_b, code;
        Point c;
        code_a = vcode(r, a);
        code_b = vcode(r, b);
        while (code_a != 0 || code_b != 0) {
            if ((code_a & code_b) != 0)
                return false;
            if (code_a != 0) {
                code = code_a;
                c = a;
            } else {
                code = code_b;
                c = b;
            }
            if ((code & LEFT) != 0) {
                c.y += (a.y - b.y) * (r.left - c.x) / (a.x - b.x);
                c.x = r.left;
            } else if ((code & RIGHT) != 0) {
                c.y += (a.y - b.y) * (r.right - c.x) / (a.x - b.x);
                c.x = r.right;
            }
            if ((code & TOP) != 0) {
                c.x += (a.x - b.x) * (r.top - c.y) / (a.y - b.y);
                c.y = r.top;
            } else if ((code & BOTTOM) != 0) {
                c.x += (a.x - b.x) * (r.bottom - c.y) / (a.y - b.y);
                c.y = r.bottom;
            }
            if (code == code_a)
                code_a = vcode(r, a);
            else
                code_b = vcode(r, b);
        }
        return true;
    }

    public static QBezierControls interpolateCubicBezierControl(Point p0, Point p1, Point p2, Point p3) {
        return interpolateCubeBezierSmooth(p0, p1, p2, p3, 1.0f);
        //    int __p0X        = p0.x;
//    int __p0Y        = p0.y;
//    int __p3X         = p3.x;
//    int __p3Y         = p3.y;
//
//    // currently, this method auto-parameterizes the curve using chord-length parameterization.  
//    // A future version might allow inputting the two t-values, but this is more
//    // user-friendly (what an over-used term :)  As an exercise, try uniform parameterization - t1 = 13/ and 52 = 2/3.
//    int deltaX = p1.x - p0.x;
//    int deltaY = p1.y - p0.y;
//    float d1     = (float)Math.sqrt(deltaX*deltaX + deltaY*deltaY);
//
//    deltaX        = p2.x - p1.x;
//    deltaY        = p2.y - p1.y;
//    float d2     = (float) Math.sqrt(deltaX*deltaX + deltaY*deltaY);
//
//    deltaX        = p3.x - p2.x;
//    deltaY        = p3.y - p2.y;
//    float d3     = (float)Math.sqrt(deltaX*deltaX + deltaY*deltaY);
//
//    float d = d1 + d2 + d3;
//    float __t1 = d1/d;
//    float __t2 = (d1+d2)/d;
//
//    // there are four unknowns (x- and y-coords for P1 and P2), which are solved as two separate sets of two equations in two unknowns
//    float t12 = __t1*__t1;
//    float t13 = __t1*t12;
//
//    float t22 = __t2*__t2;
//    float t23 = __t2*t22;
//
//    // x-coordinates of P1 and P2 (t = t1 and t2) - exercise: eliminate redudant 
//    // computations in these equations
//    float a11 = 3*t13 - 6*t12 + 3*__t1;
//    float a12 = -3*t13 + 3*t12;
//    float a21 = 3*t23 - 6*t22 + 3*__t2;
//    float a22 = -3*t23 + 3*t22;
//
//    float b1 = -t13*__p3X + __p0X*(t13 - 3*t12 + 3*__t1 -1) + p1.x;
//    float b2 = -t23*__p3X + __p0X*(t23 - 3*t22 + 3*__t2 -1) + p2.x;
//
//    Solve2x2 s = new Solve2x2();
//    PointF p = s.solve(a11, a12, a21, a22, b1, b2, 0, false);
//
//    float __p1X       = p.x;
//    float __p2X       = p.y;
//
//    // y-coordinates of P1 and P2 (t = t1 and t2)      
//    b1 = -t13*__p3Y + __p0Y*(t13 - 3*t12 + 3*__t1 -1) + p1.y;
//    b2 = -t23*__p3Y + __p0Y*(t23 - 3*t22 + 3*__t2 -1) + p2.y;
//
//    // resolving with same coefficients, but new RHS
//    p     = s.solve(a11, a12, a21, a22, b1, b2, ZERO_TOLERANCE, true);
//    float __p1Y = p.x;
//    float __p2Y = p.y;
//
//    return new QBezierControls(__p1X, __p1Y, __p2X, __p2Y);
    }

}