You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by ke...@apache.org on 2001/02/23 05:37:02 UTC
cvs commit: xml-fop/src/org/apache/fop/pdf PDFNumber.java
keiron 01/02/22 20:37:01
Modified: src/org/apache/fop/render/pdf SVGRenderer.java
src/org/apache/fop/pdf PDFNumber.java
Log:
handles non-rotated arcs
currently uses lines to draw the arc
Revision Changes Path
1.7 +133 -124 xml-fop/src/org/apache/fop/render/pdf/SVGRenderer.java
Index: SVGRenderer.java
===================================================================
RCS file: /home/cvs/xml-fop/src/org/apache/fop/render/pdf/SVGRenderer.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- SVGRenderer.java 2001/02/11 00:48:16 1.6
+++ SVGRenderer.java 2001/02/23 04:37:01 1.7
@@ -1,4 +1,4 @@
-/*-- $Id: SVGRenderer.java,v 1.6 2001/02/11 00:48:16 arved Exp $ --
+/*-- $Id: SVGRenderer.java,v 1.7 2001/02/23 04:37:01 keiron Exp $ --
============================================================================
The Apache Software License, Version 1.1
@@ -594,129 +594,24 @@
lastx += vals[0];
lasty += vals[1];
break;
- // get angle between the two points
- // then get angle of points to centre (ie. both points are on the
- // apogee and perigee of the ellipse)
- // then work out the direction from flags
case SVGPathSeg.PATHSEG_ARC_ABS:
{
-/* double rx = vals[0];
- double ry = vals[1];
- double theta = vals[2];
- boolean largearcflag = (vals[3] == 1.0);
- boolean sweepflag = (vals[4] == 1.0);
-
- double angle = Math.atan((vals[6] - lasty) /
- (vals[5] - lastx));
- double relangle = Math.acos(rx /
- Math.sqrt((vals[6] - lasty) *
- (vals[6] - lasty) +
- (vals[5] - lastx) * (vals[5] - lastx)));
- double absangle = angle + relangle;
- // change sign depending on flags
- double contrx1;
- double contry1;
- double contrx2;
- double contry2;
- if (largearcflag) {
- if (sweepflag) {
- contrx1 = lastx - rx * Math.cos(absangle);
- contry1 = lasty + rx * Math.sin(absangle);
- contrx2 = vals[5] + ry * Math.cos(absangle);
- contry2 = vals[6] + ry * Math.sin(absangle);
- } else {
- contrx1 = lastx - rx * Math.cos(absangle);
- contry1 = lasty - rx * Math.sin(absangle);
- contrx2 = vals[5] + ry * Math.cos(absangle);
- contry2 = vals[6] - ry * Math.sin(absangle);
- }
- } else {
- if (sweepflag) {
- contrx1 = lastx + rx * Math.cos(absangle);
- contry1 = lasty + rx * Math.sin(absangle);
- contrx2 = contrx1;
- contry2 = contry1;
- } else {
- contrx1 = lastx + ry * Math.cos(absangle);
- contry1 = lasty - ry * Math.sin(absangle);
- contrx2 = contrx1;
- contry2 = contry1;
- }
- }
-
- double cx = lastx;
- double cy = lasty;
- currentStream.write(pdfNumber.doubleOut(contrx1) + " " + pdfNumber.doubleOut(contry1) +
- " " + pdfNumber.doubleOut(contrx2) + " " + pdfNumber.doubleOut(contry2) + " " +
- pdfNumber.doubleOut(vals[5]) + " " + pdfNumber.doubleOut(vals[6]) + " c\n");
- lastcx = 0; //??
- lastcy = 0; //??
- lastx = vals[5];
- lasty = vals[6];*/
+ addArc(lastx, lasty, vals[0], vals[1], vals[2], (vals[3] != 0.0), (vals[4] != 0.0),
+ vals[5], vals[6]);
+ lastcx = 0; //??
+ lastcy = 0; //??
+ lastx = vals[5];
+ lasty = vals[6];
}
break;
case SVGPathSeg.PATHSEG_ARC_REL:
{
-/* double rx = vals[0];
- double ry = vals[1];
- double theta = vals[2];
- boolean largearcflag = (vals[3] == 1.0);
- boolean sweepflag = (vals[4] == 1.0);
-
- double angle = Math.atan(vals[6] / vals[5]);
- double relangle = Math.atan(ry / rx);
- // System.out.println((theta * Math.PI / 180f) + ":" + relangle + ":" + largearcflag + ":" + sweepflag);
- double absangle = (theta * Math.PI / 180f);//angle + relangle;
- // change sign depending on flags
- double contrx1;
- double contry1;
- double contrx2;
- double contry2;
- if (largearcflag) {
- // in a large arc we need to do at least 2 and a bit
- // segments or curves.
- if (sweepflag) {
- contrx1 = lastx + rx * Math.cos(absangle);
- contry1 = lasty + rx * Math.sin(absangle);
- contrx2 = lastx + vals[5] +
- ry * Math.cos(absangle);
- contry2 = lasty + vals[6] -
- ry * Math.sin(absangle);
- } else {
- contrx1 = lastx + rx * Math.sin(absangle);
- contry1 = lasty + rx * Math.cos(absangle);
- contrx2 = lastx + vals[5] +
- ry * Math.cos(absangle);
- contry2 = lasty + vals[6] +
- ry * Math.sin(absangle);
- }
- } else {
- // only need at most two segments
- if (sweepflag) {
- contrx1 = lastx + rx * Math.cos(absangle);
- contry1 = lasty - rx * Math.sin(absangle);
- contrx2 = contrx1;
- contry2 = contry1;
- } else {
- contrx1 = lastx - ry * Math.cos(absangle);
- contry1 = lasty + ry * Math.sin(absangle);
- contrx2 = contrx1;
- contry2 = contry1;
- }
- }
- //System.out.println(contrx1 + ":" + contry1 + ":" + contrx2 + ":" + contry2);
-
- double cx = lastx;
- double cy = lasty;
- currentStream.write(pdfNumber.doubleOut(contrx1) + " " + pdfNumber.doubleOut(contry1) +
- " " + pdfNumber.doubleOut(contrx2) + " " + pdfNumber.doubleOut(contry2) + " " +
- pdfNumber.doubleOut(vals[5] + lastx) + " " +
- pdfNumber.doubleOut(vals[6] + lasty) + " c\n");
-
- lastcx = 0; //??
- lastcy = 0; //??
- lastx += vals[5];
- lasty += vals[6];*/
+ addArc(lastx, lasty, vals[0], vals[1], vals[2], (vals[3] != 0.0), (vals[4] != 0.0),
+ lastx + vals[5], lasty + vals[6]);
+ lastcx = 0; //??
+ lastcy = 0; //??
+ lastx += vals[5];
+ lasty += vals[6];
}
break;
case SVGPathSeg.PATHSEG_CLOSEPATH:
@@ -757,6 +652,120 @@
return vals;
}
+ protected void addArc(double startx, double starty, double rx, double ry,
+ double angle,
+ boolean largeArcFlag,
+ boolean sweepFlag,
+ double x, double y)
+ {
+ PDFNumber pdfNumber = new PDFNumber();
+ if((startx == x) && (starty == y)) {
+ return;
+ }
+ // Ensure radii are valid
+ if (rx == 0 || ry == 0) {
+ currentStream.write(pdfNumber.doubleOut(x) + " " + pdfNumber.doubleOut(y) + " l\n");
+ return;
+ }
+ if(rx < 0)
+ rx = -rx;
+ if(ry < 0)
+ ry = -ry;
+ // Convert angle from degrees to radians
+ angle = Math.toRadians(angle % 360.0);
+
+ double x0 = startx;
+ double y0 = starty;
+ // Compute the half distance between the current and the final point
+ double dx2 = (x0 - x) / 2.0;
+ double dy2 = (y0 - y) / 2.0;
+
+ double cosAngle = Math.cos(angle);
+ double sinAngle = Math.sin(angle);
+
+ // Step 1 : Compute (x1, y1)
+ double x1 = (cosAngle * dx2 + sinAngle * dy2);
+ double y1 = (-sinAngle * dx2 + cosAngle * dy2);
+
+ double Prx = rx * rx;
+ double Pry = ry * ry;
+ double Px1 = x1 * x1;
+ double Py1 = y1 * y1;
+ // check that radii are large enough
+ double radiiCheck = Px1/Prx + Py1/Pry;
+ if (radiiCheck > 1) {
+ rx = Math.sqrt(radiiCheck) * rx;
+ ry = Math.sqrt(radiiCheck) * ry;
+ Prx = rx * rx;
+ Pry = ry * ry;
+ }
+
+ // Step 2 : Compute (cx1, cy1)
+ double sign = (largeArcFlag == sweepFlag) ? -1 : 1;
+ double sq = ((Prx*Pry)-(Prx*Py1)-(Pry*Px1)) / ((Prx*Py1)+(Pry*Px1));
+ sq = (sq < 0) ? 0 : sq;
+ double coef = (sign * Math.sqrt(sq));
+ double cx1 = coef * ((rx * y1) / ry);
+ double cy1 = coef * -((ry * x1) / rx);
+
+ // Step 3 : Compute (cx, cy) from (cx1, cy1)
+ double sx2 = (x0 + x) / 2.0;
+ double sy2 = (y0 + y) / 2.0;
+ double cx = sx2 + (cosAngle * cx1 - sinAngle * cy1);
+ double cy = sy2 + (sinAngle * cx1 + cosAngle * cy1);
+
+ // Step 4 : Compute the angleStart (angle1) and the angleExtent (dangle)
+ double ux = (x1 - cx1) / rx;
+ double uy = (y1 - cy1) / ry;
+ double vx = (-x1 - cx1) / rx;
+ double vy = (-y1 - cy1) / ry;
+ double p, n;
+ // Compute the angle start
+ n = Math.sqrt((ux * ux) + (uy * uy));
+ p = ux; // (1 * ux) + (0 * uy)
+ sign = (uy < 0) ? -1d : 1d;
+ double angleStart = Math.toDegrees(sign * Math.acos(p / n));
+
+ // Compute the angle extent
+ n = Math.sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy));
+ p = ux * vx + uy * vy;
+ sign = (ux * vy - uy * vx < 0) ? -1d : 1d;
+ double angleExtent = Math.toDegrees(sign * Math.acos(p / n));
+ if(!sweepFlag && angleExtent > 0) {
+ angleExtent -= 360f;
+ } else if (sweepFlag && angleExtent < 0) {
+ angleExtent += 360f;
+ }
+ angleExtent %= 360f;
+ angleStart %= 360f;
+
+ // arc attempt with lines
+// System.out.println("start:" + angleStart + " : " + angleExtent + " sweep:" + sweepFlag);
+ double newx = startx;
+ double newy = starty;
+ double currentAngle = angleStart + angle;
+ boolean wrap = (sweepFlag ? angleStart > angleExtent : angleStart < angleExtent);
+ boolean wrapped = false;
+
+/* newx = Math.cos(Math.toRadians(angle)) * rx * Math.cos(Math.toRadians(currentAngle)) - Math.sin(Math.toRadians(angle)) * ry * Math.sin(Math.toRadians(currentAngle)) + cx;
+ newy = Math.sin(Math.toRadians(angle)) * rx * Math.cos(Math.toRadians(currentAngle)) + Math.cos(Math.toRadians(angle)) * ry * Math.sin(Math.toRadians(currentAngle)) + cy;
+ System.out.println("ox:" + startx + " oy: " + starty + " nx:" + newx + " ny:" + newy);
+ newx = Math.cos(Math.toRadians(angle)) * rx * Math.cos(Math.toRadians(angleStart + angleExtent)) - Math.sin(Math.toRadians(angle)) * ry * Math.sin(Math.toRadians(angleStart + angleExtent)) + cx;
+ newy = Math.sin(Math.toRadians(angle)) * rx * Math.cos(Math.toRadians(angleStart + angleExtent)) + Math.cos(Math.toRadians(angle)) * ry * Math.sin(Math.toRadians(angleStart + angleExtent)) + cy;
+ System.out.println("ox:" + x + " oy: " + y + " nx:" + newx + " ny:" + newy);*/
+
+ while(true) {
+ newx = Math.cos(Math.toRadians(angle)) * rx * Math.cos(Math.toRadians(currentAngle)) - Math.sin(Math.toRadians(angle)) * ry * Math.sin(Math.toRadians(currentAngle)) + cx;
+ newy = Math.sin(Math.toRadians(angle)) * rx * Math.cos(Math.toRadians(currentAngle)) + Math.cos(Math.toRadians(angle)) * ry * Math.sin(Math.toRadians(currentAngle)) + cy;
+ currentStream.write(pdfNumber.doubleOut(newx) + " " + pdfNumber.doubleOut(newy) + " l\n");
+ currentAngle = (currentAngle + (sweepFlag ? 1 : -1) * 5.0);
+ if((sweepFlag && currentAngle > (angleStart + angleExtent)) || (!sweepFlag && currentAngle < (angleStart + angleExtent))) {
+ break;
+ }
+ }
+ currentStream.write(pdfNumber.doubleOut(x) + " " + pdfNumber.doubleOut(y) + " l\n");
+ }
+
/**
* Adds an SVG polyline or polygon.
* A polygon is merely a closed polyline.
@@ -1958,12 +1967,12 @@
for (int count = 0; count < list.getNumberOfItems(); count++) {
SVGMatrix matrix =
((SVGTransform) list.getItem(count)).getMatrix();
- currentStream.write(pdfNumber.doubleOut(matrix.getA()) +
- " " + pdfNumber.doubleOut(matrix.getB()) + " " +
- pdfNumber.doubleOut(matrix.getC()) + " " +
- pdfNumber.doubleOut(matrix.getD()) + " " +
- pdfNumber.doubleOut(matrix.getE()) + " " +
- pdfNumber.doubleOut(matrix.getF()) + " cm\n");
+ currentStream.write(pdfNumber.doubleOut(matrix.getA(), 5) +
+ " " + pdfNumber.doubleOut(matrix.getB(), 5) + " " +
+ pdfNumber.doubleOut(matrix.getC(), 5) + " " +
+ pdfNumber.doubleOut(matrix.getD(), 5) + " " +
+ pdfNumber.doubleOut(matrix.getE(), 5) + " " +
+ pdfNumber.doubleOut(matrix.getF(), 5) + " cm\n");
}
}
1.3 +41 -1 xml-fop/src/org/apache/fop/pdf/PDFNumber.java
Index: PDFNumber.java
===================================================================
RCS file: /home/cvs/xml-fop/src/org/apache/fop/pdf/PDFNumber.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- PDFNumber.java 2000/07/11 01:14:26 1.2
+++ PDFNumber.java 2001/02/23 04:37:01 1.3
@@ -1,4 +1,4 @@
-/*-- $Id: PDFNumber.java,v 1.2 2000/07/11 01:14:26 keiron Exp $ --
+/*-- $Id: PDFNumber.java,v 1.3 2001/02/23 04:37:01 keiron Exp $ --
============================================================================
The Apache Software License, Version 1.1
@@ -127,6 +127,46 @@
if ((doubleString.length() - decimal) > 6)
{
p.append(doubleString.substring(decimal,decimal+6));
+ }
+ else
+ {
+ p.append(doubleString.substring(decimal));
+ }
+ } else {
+ p.append(doubleString);
+ }
+ }
+ return(p.toString());
+ }
+
+ public String doubleOut(double doubleDown, int dec)
+ {
+
+ StringBuffer p = new StringBuffer();
+ if(doubleDown < 0) {
+ doubleDown = -doubleDown;
+ p.append("-");
+ }
+ double trouble = doubleDown % 1;
+
+ if(trouble > (1.0 - (5.0 / (Math.pow(10.0, dec)))))
+ {
+ p.append((int)doubleDown+1);
+ }
+ else if (trouble < (5.0 / (Math.pow(10.0, dec))))
+ {
+ p.append((int)doubleDown);
+ }
+ else
+ {
+ String doubleString = new String(doubleDown+"");
+ int decimal = doubleString.indexOf(".");
+ if(decimal != -1) {
+ p.append(doubleString.substring(0, decimal));
+
+ if ((doubleString.length() - decimal) > dec)
+ {
+ p.append(doubleString.substring(decimal,decimal+dec));
}
else
{