libbluray | branch: master | Ian Curtis <[email protected]> | 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. */ _______________________________________________ libbluray-devel mailing list [email protected] https://mailman.videolan.org/listinfo/libbluray-devel
