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" : "");
+        }
     }
 
     /**