Android Open Source - gti350-lab2-android-demo Graphics Wrapper






From Project

Back to project page gti350-lab2-android-demo.

License

The source code is released under:

MIT License

If you think the Android project gti350-lab2-android-demo listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package log350.example.example6;
//www. j a v  a  2 s  . c  o  m
import android.graphics.Paint;
//import android.graphics.Paint.Style;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.Matrix;
import android.graphics.Rect;


import java.lang.Math;
import java.util.ArrayList;
//import java.awt.Color;


class GraphicsWrapper {

  Matrix originalMatrix = null;

  private int windowWidthInPixels = 10; // must be initialized to something positive
  private int windowHeightInPixels = 10; // must be initialized to something positive

  // The client may either call frame() or resize() first,
  // and we must initialize ourself differently depending on the case.
  private boolean hasFrameOrResizeBeenCalledBefore = false;

  public int getWidth() { return windowWidthInPixels; }
  public int getHeight() { return windowHeightInPixels; }


  private Paint paint = null;
  private Canvas canvas = null;
  private Rect rect = new Rect();
  private Path path = new Path();

  public void set( Paint p, Canvas c ) { this.paint = p; this.canvas = c; this.originalMatrix = c.getMatrix(); windowWidthInPixels=c.getWidth(); windowHeightInPixels=c.getHeight(); }




  private int fontHeight = 14;
  public void setFontHeight( int h ) {
    fontHeight = h;
    paint.setTextSize( fontHeight );
  }
  public int getFontHeight() {
    return fontHeight;
  }









  private float offsetXInPixels = 0;
  private float offsetYInPixels = 0;
  private float scaleFactorInWorldSpaceUnitsPerPixel = 1.0f; // greater if user is more zoomed out

  public float convertPixelsToWorldSpaceUnitsX( float XInPixels ) { return ( XInPixels - offsetXInPixels )*scaleFactorInWorldSpaceUnitsPerPixel; }
  public float convertPixelsToWorldSpaceUnitsY( float YInPixels ) { return ( YInPixels - offsetYInPixels )*scaleFactorInWorldSpaceUnitsPerPixel; }
  public Point2D convertPixelsToWorldSpaceUnits( Point2D p ) { return new Point2D(convertPixelsToWorldSpaceUnitsX(p.x()),convertPixelsToWorldSpaceUnitsY(p.y())); }

  public int convertWorldSpaceUnitsToPixelsX( float x ) { return Math.round( x / scaleFactorInWorldSpaceUnitsPerPixel + offsetXInPixels ); }
  public int convertWorldSpaceUnitsToPixelsY( float y ) { return Math.round( y / scaleFactorInWorldSpaceUnitsPerPixel + offsetYInPixels ); }
  public Point2D convertWorldSpaceUnitsToPixels( Point2D p ) { return new Point2D(convertWorldSpaceUnitsToPixelsX(p.x()),convertWorldSpaceUnitsToPixelsY(p.y())); }

  public float getScaleFactorInWorldSpaceUnitsPerPixel() { return scaleFactorInWorldSpaceUnitsPerPixel; }

  public void pan( float dx, float dy ) {
    offsetXInPixels += dx;
    offsetYInPixels += dy;
  }
  public void zoomIn(
    float zoomFactor, // greater than 1 to zoom in, between 0 and 1 to zoom out
    float centerXInPixels,
    float centerYInPixels
  ) {
    scaleFactorInWorldSpaceUnitsPerPixel /= zoomFactor;
    offsetXInPixels = centerXInPixels - (centerXInPixels - offsetXInPixels) * zoomFactor;
    offsetYInPixels = centerYInPixels - (centerYInPixels - offsetYInPixels) * zoomFactor;
  }
  public void zoomIn(
    float zoomFactor // greater than 1 to zoom in, between 0 and 1 to zoom out
  ) {
    zoomIn( zoomFactor, windowWidthInPixels * 0.5f, windowHeightInPixels * 0.5f );
  }

  // This can be used to implement bimanual (2-handed) camera control,
  // or 2-finger camera control, as in a "pinch" gesture
  public void panAndZoomBasedOnDisplacementOfTwoPoints(
    // these are assumed to be in pixel coordinates
    Point2D A_old, Point2D B_old,
    Point2D A_new, Point2D B_new
  ) {
    // Compute midpoints of each pair of points
    Point2D M1 = Point2D.average( A_old, B_old );
    Point2D M2 = Point2D.average( A_new, B_new );

    // This is the translation that the world should appear to undergo.
    Vector2D translation = Point2D.diff( M2, M1 );

    // Compute a vector associated with each pair of points.
    Vector2D v1 = Point2D.diff( A_old, B_old );
    Vector2D v2 = Point2D.diff( A_new, B_new );

    float v1_length = v1.length();
    float v2_length = v2.length();
    float scaleFactor = 1;
    if ( v1_length > 0 && v2_length > 0 )
      scaleFactor = v2_length / v1_length;
    pan( translation.x(), translation.y() );
    zoomIn( scaleFactor, M2.x(), M2.y() );
  }

  public void frame(
    AlignedRectangle2D rect,
    boolean expand // true if caller wants a margin of whitespace added around the rect
  ) {
    hasFrameOrResizeBeenCalledBefore = true;
    assert windowWidthInPixels > 0 && windowHeightInPixels > 0;

    if ( rect.isEmpty() || rect.getDiagonal().x() == 0 || rect.getDiagonal().y() == 0 ) {
      return;
    }
    if ( expand ) {
      float diagonal = rect.getDiagonal().length() / 20;
      Vector2D v = new Vector2D( diagonal, diagonal );
      rect = new AlignedRectangle2D( Point2D.diff(rect.getMin(),v), Point2D.sum(rect.getMax(),v) );
    }
    if ( rect.getDiagonal().x() / rect.getDiagonal().y() >= windowWidthInPixels / (float)windowHeightInPixels ) {
      offsetXInPixels = - rect.getMin().x() * windowWidthInPixels / rect.getDiagonal().x();
      scaleFactorInWorldSpaceUnitsPerPixel = rect.getDiagonal().x() / windowWidthInPixels;
      offsetYInPixels = windowHeightInPixels/2 - rect.getCenter().y() / scaleFactorInWorldSpaceUnitsPerPixel;
    }
    else {
      offsetYInPixels = - rect.getMin().y() * windowHeightInPixels / rect.getDiagonal().y();
      scaleFactorInWorldSpaceUnitsPerPixel = rect.getDiagonal().y() / windowHeightInPixels;
      offsetXInPixels = windowWidthInPixels/2 - rect.getCenter().x() / scaleFactorInWorldSpaceUnitsPerPixel;
    }
  }


  public void resize( int w, int h ) {
    if ( ! hasFrameOrResizeBeenCalledBefore ) {
      windowWidthInPixels = w;
      windowHeightInPixels = h;
      hasFrameOrResizeBeenCalledBefore = true;
      return;
    }

    Point2D oldCenter = convertPixelsToWorldSpaceUnits( new Point2D(
      windowWidthInPixels * 0.5f, windowHeightInPixels * 0.5f
    ) );
    float radius = Math.min( windowWidthInPixels, windowHeightInPixels ) * 0.5f * scaleFactorInWorldSpaceUnitsPerPixel;


    windowWidthInPixels = w;
    windowHeightInPixels = h;

    if ( radius > 0 ) {
      frame(
        new AlignedRectangle2D(
          new Point2D( oldCenter.x() - radius, oldCenter.y() - radius ),
          new Point2D( oldCenter.x() + radius, oldCenter.y() + radius )
        ),
        false
      );
    }
  }

  public void setCoordinateSystemToPixels() {
    canvas.setMatrix( originalMatrix );
  }

  public void setCoordinateSystemToWorldSpaceUnits() {
    canvas.setMatrix( originalMatrix );
    canvas.translate( offsetXInPixels, offsetYInPixels );
    float s = 1.0f/scaleFactorInWorldSpaceUnitsPerPixel;
    canvas.scale( s, s );
  }

  public void clear( float r, float g, float b ) {
    canvas.drawRGB( (int)(r*255), (int)(g*255), (int)(b*255) );
  }

  public void setupForDrawing() {
  }

  public void enableAlphaBlending() {
  }

  public void disableAlphaBlending() {
  }

  public void setColor( float r, float g, float b ) {
    paint.setARGB( 255, (int)(r*255), (int)(g*255), (int)(b*255) );
  }

  public void setColor( float r, float g, float b, float alpha ) {
    paint.setARGB( (int)(alpha*255), (int)(r*255), (int)(g*255), (int)(b*255) );
  }

  public void setLineWidth( float width ) {
    paint.setStrokeWidth( width );
  }

  public void drawLine( float x1, float y1, float x2, float y2 ) {
    canvas.drawLine( x1, y1, x2, y2, paint );
  }

  public void drawPolyline( ArrayList< Point2D > points, boolean isClosed, boolean isFilled ) {
    if ( points.size() <= 1 )
      return;

    path.reset();
    Point2D p = points.get(0);
    path.moveTo( p.x(), p.y() );
    for ( int i = 1; i < points.size(); ++i ) {
      p = points.get(i);
      path.lineTo( p.x(), p.y() );
    }
    if ( isClosed )
      path.close();
    paint.setStyle( isFilled ? Paint.Style.FILL : Paint.Style.STROKE );
    // TODO FIXME XXX or should i call path.setFillType() ?
    canvas.drawPath( path, paint );
  }

  public void drawPolyline( ArrayList< Point2D > points ) {
    drawPolyline( points, false, false );
  }
  public void drawPolygon( ArrayList< Point2D > points ) {
    drawPolyline( points, true, false );
  }
  public void fillPolygon( ArrayList< Point2D > points ) {
    drawPolyline( points, true, true );
  }

  public void drawRect( float x, float y, float w, float h, boolean isFilled ) {
    paint.setStyle( isFilled ? Paint.Style.FILL : Paint.Style.STROKE );
    canvas.drawRect( x, y, x+w, y+h, paint );
  }

  public void drawRect( float x, float y, float w, float h ) {
    drawRect( x, y, w, h, false );
  }

  public void fillRect( float x, float y, float w, float h ) {
    drawRect( x, y, w, h, true );
  }

  public void drawCircle( float x, float y, float radius, boolean isFilled ) {
    paint.setStyle( isFilled ? Paint.Style.FILL : Paint.Style.STROKE );
    canvas.drawCircle( x, y, radius, paint );
  }

  public void drawCircle( float x, float y, float radius ) {
    drawCircle( x, y, radius, false );
  }

  public void fillCircle( float x, float y, float radius ) {
    drawCircle( x, y, radius, true );
  }

  public void drawCenteredCircle( float x, float y, float radius, boolean isFilled ) {
    x -= radius;
    y -= radius;
    drawCircle( x, y, radius, isFilled );
  }

  public void drawArc(
    float center_x, // increases right
    float center_y, // increases down
    float radius,
    float startAngle, // in radians; zero for right, increasing counterclockwise
    float angleExtent, // in radians; positive for counterclockwise
    boolean isFilled
  ) {
    // TODO FIXME XXX
  }

  public void drawArc(
    float center_x, float center_y, float radius,
    float startAngle, // in radians
    float angleExtent // in radians
  ) {
    drawArc( center_x, center_y, radius, startAngle, angleExtent, false );
  }

  public void fillArc(
    float center_x, float center_y, float radius,
    float startAngle, // in radians
    float angleExtent // in radians
  ) {
    drawArc( center_x, center_y, radius, startAngle, angleExtent, true );
  }



  // returns the width of a string
  public float stringWidth( String s ) {
    if ( s == null || s.length() == 0 ) return 0;

    paint.getTextBounds( s, 0, s.length(), rect );
    return rect.width();
  }


  public void drawString(
    float x, float y,      // lower left corner of the string
    String s           // the string
  ) {
    if ( s == null || s.length() == 0 ) return;
    paint.setStyle( Paint.Style.FILL );
    canvas.drawText( s, x, y, paint );
  }


}




Java Source Code List

log350.example.example6.AlignedRectangle2D.java
log350.example.example6.DrawingView.java
log350.example.example6.GraphicsWrapper.java
log350.example.example6.Log350Example6Activity.java
log350.example.example6.MyButton.java
log350.example.example6.Point2DUtil.java
log350.example.example6.Point2D.java
log350.example.example6.ShapeContainer.java
log350.example.example6.Shape.java
log350.example.example6.Vector2D.java