[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