[libbluray-devel] BD-J: implement drawArc()
Ian Curtis
git at videolan.org
Wed Nov 12 09:49:14 CET 2014
libbluray | branch: master | Ian Curtis <i.curtis at gmail.com> | Wed Nov 12 10:36:03 2014 +0200| [8e3d9054e158ead65d50823d27a49a5b430117fd] | committer: hpi1
BD-J: implement drawArc()
> http://git.videolan.org/gitweb.cgi/libbluray.git/?a=commit;h=8e3d9054e158ead65d50823d27a49a5b430117fd
---
.../bdj/java/java/awt/BDGraphicsBase.java | 198 +++++++++++++++++++-
1 file changed, 196 insertions(+), 2 deletions(-)
diff --git a/src/libbluray/bdj/java/java/awt/BDGraphicsBase.java b/src/libbluray/bdj/java/java/awt/BDGraphicsBase.java
index 0d76ea7..cea0993 100644
--- a/src/libbluray/bdj/java/java/awt/BDGraphicsBase.java
+++ b/src/libbluray/bdj/java/java/awt/BDGraphicsBase.java
@@ -748,6 +748,200 @@ abstract class BDGraphicsBase extends Graphics2D implements ConstrainableGraphic
}
}
+ private int getAngle(int centreX, int centreY, int pointX, int pointY) {
+
+ float vStartX;
+ float vStartY;
+ float vEndX;
+ float vEndY;
+ float length;
+ double angle;
+
+ vStartX = 1; // vector pointing right (this is where angle starts for arcs)
+ vStartY = 0;
+
+ vEndX = pointX - centreX;
+ vEndY = pointY - centreY;
+
+ length = (float) Math.sqrt(vEndX*vEndX + vEndY*vEndY);
+
+ vEndX /= length;
+ vEndY /= length;
+
+ angle = Math.acos(vStartX*vEndX + vStartY*vEndY);
+ angle = angle * 180.0 / Math.PI;
+
+ if (vEndY > 0) {
+ angle = 360 - angle;
+ }
+
+ return (int)(angle + 0.5);
+ }
+
+ private void drawArcI(boolean fill, int x, int y, int width, int height, int startAngle, int arcAngle) {
+
+ int endAngle;
+ int startX;
+ int endX;
+ int offset;
+ int[] xList;
+ int[] yList;
+ int count;
+ int numPoints;
+ int tempX;
+ int tempY;
+ int angle;
+ int widthDiv2;
+ int heightDiv2;
+ float as;
+ float bs;
+ boolean addedZero;
+ boolean circle;
+
+ // sanity checks
+ if (width <= 0 || height <= 0 || arcAngle == 0) {
+ return;
+ }
+
+ // init variables
+ count = 0;
+ addedZero = false;
+ circle = false;
+ widthDiv2 = (int)(width/2.0f + 0.5f);
+ heightDiv2 = (int)(height/2.0f + 0.5f);
+ numPoints = ((height + 1/2) + (height + 1/2) + 1) * 2 + 1;
+ xList = new int[numPoints];
+ yList = new int[numPoints];
+
+ as = (width/2.0f) * (width/2.0f);
+ bs = (height/2.0f) * (height/2.0f);
+
+ // check if we actually want to draw a circle
+ if (Math.abs(arcAngle) >= 360) {
+ circle = true;
+ }
+
+ if (startAngle < 0) {
+ startAngle %= 360;
+ startAngle = Math.abs(startAngle);
+ startAngle = 360 - startAngle;
+ }
+
+ if (arcAngle < 0) {
+ int temp;
+ temp = startAngle;
+ endAngle = startAngle;
+ startAngle = 360 + arcAngle + temp;
+ } else {
+ endAngle = startAngle + arcAngle;
+ }
+
+ startAngle %= 360;
+ endAngle %= 360;
+
+ for (int i = heightDiv2; i >= -heightDiv2; i--) {
+ boolean hit = false;
+ int offsetAngle;
+ int startXAngle;
+
+ offset = (int) Math.sqrt( (1.0 - i*i/bs) * as );
+ startX = x + offset + widthDiv2;
+
+ offsetAngle = (int) Math.sqrt( (1.0 - i*i/bs) * bs ); // we calculate these as if it were a circle
+ startXAngle = x + offsetAngle + height/2;
+
+ tempX = startX;
+ tempY = y + i + height/2;
+
+ angle = getAngle(x + height/2, y + height/2, startXAngle, tempY);
+
+ if (startAngle < endAngle) {
+ if (angle < endAngle && angle >= startAngle) {
+ xList[count] = tempX;
+ yList[count] = tempY;
+ count++;
+ hit = true;
+ }
+ } else {
+ if (!(angle > endAngle && angle < startAngle)) {
+ xList[count] = tempX;
+ yList[count] = tempY;
+ count++;
+ hit = true;
+ }
+ }
+
+ if (!hit && !addedZero && !circle && fill) {
+ xList[count] = x + width/2;
+ yList[count] = y + height/2;
+ count++;
+ addedZero = true;
+ }
+
+ if (!hit && !fill && !circle && count > 1) {
+ drawPolyline(xList, yList, count);
+ count = 0;
+ }
+ }
+
+
+ for (int i = -heightDiv2; i <= heightDiv2; i++) {
+ boolean hit = false;
+ int offsetAngle;
+ int endXAngle;
+
+ offset = (int) Math.sqrt( (1.0 - i*i/bs) * as );
+ endX = x - offset + width/2;
+
+ offsetAngle = (int) Math.sqrt( (1.0 - i*i/bs) * bs ); // we calculate these as if it were a circle
+ endXAngle = x - offsetAngle + height/2;
+
+ tempX = endX;
+ tempY = y + i + height/2;
+
+ angle = getAngle(x + height/2, y + height/2, endXAngle, tempY);
+
+ if (startAngle < endAngle) {
+ if (angle <= endAngle && angle >= startAngle) {
+ xList[count] = tempX;
+ yList[count] = tempY;
+ count++;
+ hit = true;
+ }
+ } else {
+ if (!(angle > endAngle && angle < startAngle)) {
+ xList[count] = tempX;
+ yList[count] = tempY;
+ count++;
+ hit = true;
+ }
+ }
+
+ if (!hit && !addedZero && !circle && fill) {
+ xList[count] = x + width/2;
+ yList[count] = y + height/2;
+ count++;
+ addedZero = true;
+ }
+
+ if (!hit && !fill && !circle && count > 1) {
+ drawPolyline(xList, yList, count);
+ count = 0;
+ }
+ }
+
+ if (fill) {
+ fillPolygon(xList, yList, count);
+ } else {
+ if (circle) {
+ drawPolygon(xList, yList, count); // we need to connect start to end in the case of 360
+ } else {
+ drawPolyline(xList, yList, count); // shape must be open so no connection
+ }
+ }
+ }
+
+
/**
* Draws an arc bounded by the given rectangle from startAngle to
* endAngle. 0 degrees is a vertical line straight up from the
@@ -755,12 +949,12 @@ abstract class BDGraphicsBase extends Graphics2D implements ConstrainableGraphic
* rotations, negative angle are counter-clockwise.
*/
public void drawArc(int x, int y, int w, int h, int startAngle, int endAngle) {
- logger.unimplemented("drawArc");
+ drawArcI(false, x, y, w, h, startAngle, endAngle);
}
/** fills an arc. arguments are the same as drawArc. */
public void fillArc(int x, int y, int w, int h, int startAngle, int endAngle) {
- logger.unimplemented("fillArc");
+ drawArcI(true, x, y, w, h, startAngle, endAngle);
}
/** Draws a rounded rectangle. */
More information about the libbluray-devel
mailing list