You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by le...@apache.org on 2013/09/29 19:34:17 UTC
svn commit: r1527359 -
/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfviewer/font/TTFGlyph2D.java
Author: lehmi
Date: Sun Sep 29 17:34:17 2013
New Revision: 1527359
URL: http://svn.apache.org/r1527359
Log:
PDFBOX-1435: improved glyph rendering based as proposed by Tilman Hausherr
Modified:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfviewer/font/TTFGlyph2D.java
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfviewer/font/TTFGlyph2D.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfviewer/font/TTFGlyph2D.java?rev=1527359&r1=1527358&r2=1527359&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfviewer/font/TTFGlyph2D.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfviewer/font/TTFGlyph2D.java Sun Sep 29 17:34:17 2013
@@ -20,7 +20,6 @@ package org.apache.pdfbox.pdfviewer.font
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
-import java.awt.geom.Point2D;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@@ -45,6 +44,7 @@ import org.apache.pdfbox.pdmodel.font.PD
*
* This class is based on code from Apache Batik a subproject of Apache XMLGraphics. see
* http://xmlgraphics.apache.org/batik/ for further details.
+ *
*/
public class TTFGlyph2D implements Glyph2D
{
@@ -372,7 +372,7 @@ public class TTFGlyph2D implements Glyph
int i = 0;
boolean endOfContour = true;
Point startingPoint = null;
- Point lastCtrlPoint = null;
+ Point offCurveStartPoint = null;
while (i < numberOfPoints)
{
Point point = points[i % numberOfPoints];
@@ -388,19 +388,33 @@ public class TTFGlyph2D implements Glyph
continue;
}
// move to the starting point
- path.moveTo(point.x, point.y);
+ moveTo(path, point);
endOfContour = false;
startingPoint = point;
+
+ offCurveStartPoint = null;
+ if (!point.onCurve && !nextPoint1.onCurve)
+ {
+ // off curve start
+ offCurveStartPoint = point;
+ startingPoint = midValue(point, nextPoint1);
+ moveTo(path, startingPoint);
+ }
+ }
+
+ if (point.onCurve)
+ {
+ offCurveStartPoint = null;
}
// lineTo
if (point.onCurve && nextPoint1.onCurve)
{
- path.lineTo(nextPoint1.x, nextPoint1.y);
+ lineTo(path, nextPoint1);
i++;
if (point.endOfContour || nextPoint1.endOfContour)
{
endOfContour = true;
- path.closePath();
+ closePath(path);
}
continue;
}
@@ -410,65 +424,74 @@ public class TTFGlyph2D implements Glyph
if (nextPoint1.endOfContour)
{
// use the starting point as end point
- path.quadTo(nextPoint1.x, nextPoint1.y, startingPoint.x, startingPoint.y);
+ quadTo(path, nextPoint1, startingPoint);
}
else
{
- path.quadTo(nextPoint1.x, nextPoint1.y, nextPoint2.x, nextPoint2.y);
+ quadTo(path, nextPoint1, nextPoint2);
}
if (nextPoint1.endOfContour || nextPoint2.endOfContour)
{
endOfContour = true;
- path.closePath();
+ closePath(path);
}
i += 2;
- lastCtrlPoint = nextPoint1;
continue;
}
+
+ // TH segment for curves that start with an off-curve point
+ if (offCurveStartPoint != null && !nextPoint1.onCurve && !nextPoint2.onCurve)
+ {
+ // interpolate endPoint
+ quadTo(path, nextPoint1, midValue(nextPoint1, nextPoint2));
+ if (point.endOfContour || nextPoint1.endOfContour || nextPoint2.endOfContour)
+ {
+ quadTo(path, nextPoint2, midValue(nextPoint2, offCurveStartPoint));
+ quadTo(path, offCurveStartPoint, startingPoint);
+ endOfContour = true;
+ i += 2;
+ continue;
+ }
+ ++i;
+ continue;
+ }
+
if (point.onCurve && !nextPoint1.onCurve && !nextPoint2.onCurve)
{
// interpolate endPoint
- int endPointX = midValue(nextPoint1.x, nextPoint2.x);
- int endPointY = midValue(nextPoint1.y, nextPoint2.y);
- path.quadTo(nextPoint1.x, nextPoint1.y, endPointX, endPointY);
+ quadTo(path, nextPoint1, midValue(nextPoint1, nextPoint2));
if (point.endOfContour || nextPoint1.endOfContour || nextPoint2.endOfContour)
{
- path.quadTo(nextPoint2.x, nextPoint2.y, startingPoint.x, startingPoint.y);
+ quadTo(path, nextPoint2, startingPoint);
endOfContour = true;
- path.closePath();
+ closePath(path);
}
i += 2;
- lastCtrlPoint = nextPoint1;
continue;
}
+
+ // TH the control point is never interpolated
if (!point.onCurve && !nextPoint1.onCurve)
{
- Point2D lastEndPoint = path.getCurrentPoint();
- // calculate new control point using the previous control point
- lastCtrlPoint = new Point(midValue(lastCtrlPoint.x, (int) lastEndPoint.getX()), midValue(
- lastCtrlPoint.y, (int) lastEndPoint.getY()));
- // interpolate endPoint
- int endPointX = midValue((int) lastEndPoint.getX(), nextPoint1.x);
- int endPointY = midValue((int) lastEndPoint.getY(), nextPoint1.y);
- path.quadTo(lastCtrlPoint.x, lastCtrlPoint.y, endPointX, endPointY);
+ quadTo(path, point, midValue(point, nextPoint1));
if (point.endOfContour || nextPoint1.endOfContour)
{
endOfContour = true;
- path.closePath();
+ quadTo(path, nextPoint1, startingPoint);
}
i++;
continue;
}
+
if (!point.onCurve && nextPoint1.onCurve)
{
- path.quadTo(point.x, point.y, nextPoint1.x, nextPoint1.y);
+ quadTo(path, point, nextPoint1);
if (point.endOfContour || nextPoint1.endOfContour)
{
endOfContour = true;
- path.closePath();
+ closePath(path);
}
i++;
- lastCtrlPoint = point;
continue;
}
LOG.error("Unknown glyph command!!");
@@ -477,11 +500,40 @@ public class TTFGlyph2D implements Glyph
return path;
}
+ private void closePath(GeneralPath path)
+ {
+ path.closePath();
+ LOG.debug("closePath");
+ }
+
+ private void moveTo(GeneralPath path, Point point)
+ {
+ path.moveTo(point.x, point.y);
+ LOG.debug("moveTo: " + String.format("%d,%d", point.x, point.y));
+ }
+
+ private void lineTo(GeneralPath path, Point point)
+ {
+ path.lineTo(point.x, point.y);
+ LOG.debug("lineTo: " + String.format("%d,%d", point.x, point.y));
+ }
+
+ private void quadTo(GeneralPath path, Point ctrlPoint, Point point)
+ {
+ path.quadTo(ctrlPoint.x, ctrlPoint.y, point.x, point.y);
+ LOG.debug("quadTo: " + String.format("%d,%d %d,%d", ctrlPoint.x, ctrlPoint.y, point.x, point.y));
+ }
+
private int midValue(int a, int b)
{
return a + (b - a) / 2;
}
+ private Point midValue(Point point1, Point point2)
+ {
+ return new Point(midValue(point1.x, point2.x), midValue(point1.y, point2.y));
+ }
+
/**
* This class represents one point of a glyph.
*
@@ -506,6 +558,13 @@ public class TTFGlyph2D implements Glyph
{
this(xValue, yValue, false, false);
}
+
+ @Override
+ public String toString()
+ {
+ return String.format("Point(%d,%d,%s,%s)", x, y, onCurve ? "onCurve" : "",
+ endOfContour ? "endOfContour" : "");
+ }
}
/**