Path: blob/master/SLICK_HOME/src/org/newdawn/slick/geom/RoundedRectangle.java
1461 views
package org.newdawn.slick.geom;12import java.util.ArrayList;3import java.util.List;45import org.newdawn.slick.util.FastTrig;67/**8* Class to create rounded rectangles with.9*10* @author Mark Bernard11*/12public class RoundedRectangle extends Rectangle {13/** Indicates the top left corner should be rounded */14public static final int TOP_LEFT = 1;15/** Indicates the top right corner should be rounded */16public static final int TOP_RIGHT = 2;17/** Indicates the bottom right corner should be rounded */18public static final int BOTTOM_RIGHT = 4;19/** Indicates the bottom left corner should be rounded */20public static final int BOTTOM_LEFT = 8;21/** Indicates the all cornders should be rounded */22public static final int ALL = TOP_LEFT | TOP_RIGHT | BOTTOM_RIGHT | BOTTOM_LEFT;2324/** Default number of segments to draw the rounded corners with */25private static final int DEFAULT_SEGMENT_COUNT = 25;2627/** radius of each corner */28private float cornerRadius;29/** number of segments for each corner */30private int segmentCount;31/** The flags indicating which corners should be rounded */32private int cornerFlags;3334/**35* Construct a rectangle with rounded corners.36*37* @param x The x position of the rectangle.38* @param y The y position of the rectangle.39* @param width The width of the rectangle.40* @param height The hieght of the rectangle.41* @param cornerRadius The radius to use for the arc in each corner.42*/43public RoundedRectangle(float x, float y, float width, float height, float cornerRadius) {44this(x, y, width, height, cornerRadius, DEFAULT_SEGMENT_COUNT);45}4647/**48* Construct a rectangle with rounded corners.49*50* @param x The x position of the rectangle.51* @param y The y position of the rectangle.52* @param width The width of the rectangle.53* @param height The hieght of the rectangle.54* @param cornerRadius The radius to use for the arc in each corner.55* @param segmentCount The number of segments to use to draw each corner arc.56*/57public RoundedRectangle(float x, float y, float width, float height, float cornerRadius, int segmentCount) {58this(x,y,width,height,cornerRadius,segmentCount,ALL);59}6061/**62* Construct a rectangle with rounded corners.63*64* @param x The x position of the rectangle.65* @param y The y position of the rectangle.66* @param width The width of the rectangle.67* @param height The hieght of the rectangle.68* @param cornerRadius The radius to use for the arc in each corner.69* @param segmentCount The number of segments to use to draw each corner arc.70* @param cornerFlags Indicates which corners should be rounded71*/72public RoundedRectangle(float x, float y, float width, float height,73float cornerRadius, int segmentCount, int cornerFlags) {74super(x,y,width,height);7576if(cornerRadius < 0) {77throw new IllegalArgumentException("corner radius must be >= 0");78}79this.x = x;80this.y = y;81this.width = width;82this.height = height;83this.cornerRadius = cornerRadius;84this.segmentCount = segmentCount;85this.pointsDirty = true;86this.cornerFlags = cornerFlags;87}8889/**90* Get the radius for each corner.91*92* @return The radius for each corner.93*/94public float getCornerRadius() {95return cornerRadius;96}9798/**99* Set the radius for each corner.100*101* @param cornerRadius The radius for each corner to set.102*/103public void setCornerRadius(float cornerRadius) {104if (cornerRadius >= 0) {105if (cornerRadius != this.cornerRadius) {106this.cornerRadius = cornerRadius;107pointsDirty = true;108}109}110}111112/**113* Get the height of this rectangle.114*115* @return The height of this rectangle.116*/117public float getHeight() {118return height;119}120121/**122* Set the height of this rectangle.123*124* @param height The height to set.125*/126public void setHeight(float height) {127if (this.height != height) {128this.height = height;129pointsDirty = true;130}131}132133/**134* Get the width of this rectangle.135*136* @return The width of this rectangle.137*/138public float getWidth() {139return width;140}141142/**143* Set the width of this rectangle.144*145* @param width The width to set.146*/147public void setWidth(float width) {148if (width != this.width) {149this.width = width;150pointsDirty = true;151}152}153154protected void createPoints() {155maxX = x + width;156maxY = y + height;157minX = x;158minY = y;159float useWidth = width - 1;160float useHeight = height - 1;161if(cornerRadius == 0) {162points = new float[8];163164points[0] = x;165points[1] = y;166167points[2] = x + useWidth;168points[3] = y;169170points[4] = x + useWidth;171points[5] = y + useHeight;172173points[6] = x;174points[7] = y + useHeight;175}176else {177float doubleRadius = cornerRadius * 2;178if(doubleRadius > useWidth) {179doubleRadius = useWidth;180cornerRadius = doubleRadius / 2;181}182if(doubleRadius > useHeight) {183doubleRadius = useHeight;184cornerRadius = doubleRadius / 2;185}186187ArrayList tempPoints = new ArrayList();188//the outer most set of points for each arc will also ac as the points that start the189//straight sides, so the straight sides do not have to be added.190191//top left corner arc192if ((cornerFlags & TOP_LEFT) != 0) {193tempPoints.addAll(createPoints(segmentCount, cornerRadius, x + cornerRadius, y + cornerRadius, 180, 270));194} else {195tempPoints.add(new Float(x));196tempPoints.add(new Float(y));197}198199//top right corner arc200if ((cornerFlags & TOP_RIGHT) != 0) {201tempPoints.addAll(createPoints(segmentCount, cornerRadius, x + useWidth - cornerRadius, y + cornerRadius, 270, 360));202} else {203tempPoints.add(new Float(x+useWidth));204tempPoints.add(new Float(y));205}206207//bottom right corner arc208if ((cornerFlags & BOTTOM_RIGHT) != 0) {209tempPoints.addAll(createPoints(segmentCount, cornerRadius, x + useWidth - cornerRadius, y + useHeight - cornerRadius, 0, 90));210} else {211tempPoints.add(new Float(x+useWidth));212tempPoints.add(new Float(y+useHeight));213}214215//bottom left corner arc216if ((cornerFlags & BOTTOM_LEFT) != 0) {217tempPoints.addAll(createPoints(segmentCount, cornerRadius, x + cornerRadius, y + useHeight - cornerRadius, 90, 180));218} else {219tempPoints.add(new Float(x));220tempPoints.add(new Float(y+useHeight));221}222223points = new float[tempPoints.size()];224for(int i=0;i<tempPoints.size();i++) {225points[i] = ((Float)tempPoints.get(i)).floatValue();226}227}228229findCenter();230calculateRadius();231}232233/**234* Generate the points to fill a corner arc.235*236* @param numberOfSegments How fine to make the ellipse.237* @param radius The radius of the arc.238* @param cx The x center of the arc.239* @param cy The y center of the arc.240* @param start The start angle of the arc.241* @param end The end angle of the arc.242* @return The points created.243*/244private List createPoints(int numberOfSegments, float radius, float cx, float cy, float start, float end) {245ArrayList tempPoints = new ArrayList();246247int step = 360 / numberOfSegments;248249for (float a=start;a<=end+step;a+=step) {250float ang = a;251if (ang > end) {252ang = end;253}254float x = (float) (cx + (FastTrig.cos(Math.toRadians(ang)) * radius));255float y = (float) (cy + (FastTrig.sin(Math.toRadians(ang)) * radius));256257tempPoints.add(new Float(x));258tempPoints.add(new Float(y));259}260261return tempPoints;262}263/**264* Apply a transformation and return a new shape. This will not alter the current shape but will265* return the transformed shape.266*267* @param transform The transform to be applied268* @return The transformed shape.269*/270public Shape transform(Transform transform) {271checkPoints();272273Polygon resultPolygon = new Polygon();274275float result[] = new float[points.length];276transform.transform(points, 0, result, 0, points.length / 2);277resultPolygon.points = result;278resultPolygon.findCenter();279280return resultPolygon;281}282283}284285286