This fixes the hinting of strong points and the computation of inflection points in the autohinter.
2007-01-04 Roman Kennke <[EMAIL PROTECTED]> * gnu/java/awt/font/autofit/GlyphHints.java (alignStrongPoints): Don't special case the vertical dimension. (computeInflectionPoints): Corrected computation of inflection points. * gnu/java/awt/font/autofit/Utils.java (ANGLE_4PI): Removed. (ANGLE_PI2): New constant for PI/2. (ANGLE_PI4): New constant for PI/4. (angleDiff): Fixed. (atan): Fixed. /Roman
Index: gnu/java/awt/font/autofit/GlyphHints.java =================================================================== RCS file: /cvsroot/classpath/classpath/gnu/java/awt/font/autofit/GlyphHints.java,v retrieving revision 1.6 diff -u -1 -5 -r1.6 GlyphHints.java --- gnu/java/awt/font/autofit/GlyphHints.java 16 Dec 2006 20:51:02 -0000 1.6 +++ gnu/java/awt/font/autofit/GlyphHints.java 4 Jan 2007 10:29:04 -0000 @@ -200,62 +200,63 @@ } computeInflectionPoints(); } private void setWeakPoint(Point p) { p.setFlags((byte) (p.getFlags() | Point.FLAG_WEAK_INTERPOLATION)); } /** * Computes the inflection points for a glyph. */ private void computeInflectionPoints() { // Do each contour separately. - for (int c = 0; c < contours.length; c++) + contours : for (int c = 0; c < contours.length; c++) { Point point = contours[c]; Point first = point; Point start = point; Point end = point; do { end = end.getNext(); if (end == first) - return; + continue contours; } while (end.getOrigX() == first.getOrigX() && end.getOrigY() == first.getOrigY()); - - // Extend segment whenever possible. + + // Extend segment start whenever possible. Point before = start; int angleIn; int angleSeg = Utils.atan(end.getOrigX() - start.getOrigX(), end.getOrigY() - start.getOrigY()); do { do { start = before; before = before.getPrev(); if (before == first) - return; + continue contours; } while (before.getOrigX() == start.getOrigX() && before.getOrigY() == start.getOrigY()); angleIn = Utils.atan(start.getOrigX() - before.getOrigX(), start.getOrigY() - before.getOrigY()); } while (angleIn == angleSeg); + first = start; int diffIn = Utils.angleDiff(angleIn, angleSeg); // Now, process all segments in the contour. Point after; boolean finished = false; int angleOut, diffOut; do { // First, extend the current segment's end whenever possible. after = end; do { do { end = after; @@ -494,41 +495,41 @@ int u, ou, fu, delta; if (dim == DIMENSION_VERT) { u = point.getOrigY(); ou = point.getScaledY(); } else { u = point.getOrigX(); ou = point.getScaledX(); } fu = u; // Is the point before the first edge? Edge edge = edges[0]; // Inversed vertical dimension. - delta = dim == DIMENSION_HORZ ? edge.fpos - u : u - edge.fpos; + delta = edge.fpos - u; if (delta >= 0) { u = edge.pos - (edge.opos - ou); storePoint(point, u, dim, touchFlag); } else { // Is the point after the last edge? edge = edges[numEdges - 1]; - delta = dim == DIMENSION_HORZ ? u - edge.fpos : edge.fpos - u; + delta = u - edge.fpos; if (delta >= 0) { u = edge.pos + (ou - edge.opos); storePoint(point, u, dim, touchFlag); } else { // Find enclosing edges. int min = 0; int max = numEdges; int mid, fpos; boolean found = false; while (min < max) { mid = (max + min) / 2; Index: gnu/java/awt/font/autofit/Utils.java =================================================================== RCS file: /cvsroot/classpath/classpath/gnu/java/awt/font/autofit/Utils.java,v retrieving revision 1.3 diff -u -1 -5 -r1.3 Utils.java --- gnu/java/awt/font/autofit/Utils.java 15 Dec 2006 00:59:46 -0000 1.3 +++ gnu/java/awt/font/autofit/Utils.java 4 Jan 2007 10:29:04 -0000 @@ -73,32 +73,33 @@ 46, 46, 46, 46, 46, 47, 47, 47, 47, 48, 48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, 59, 59, 59, 59, 59, 59, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, 61, 62, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 63, 64, 64, 64 }; private static final int ANGLE_PI = 256; + private static final int ANGLE_PI2 = ANGLE_PI / 2; + private static final int ANGLE_PI4 = ANGLE_PI / 4; private static final int ANGLE_2PI = ANGLE_PI * 2; - private static final int ANGLE_4PI = ANGLE_PI * 4; /** * Computes the direction constant for the specified vector. The vector is * given as differential value already. * * @param dx the x vector * @param dy the y vector * * @return the direction of that vector, or DIR_NONE, if that vector is not * approximating against one of the major axises */ static int computeDirection(int dx, int dy) { int dir = DIR_NONE; if (dx < 0) @@ -139,72 +140,77 @@ } public static int atan(int dx, int dy) { int angle; // Trivial cases. if (dy == 0) { angle = 0; if (dx < 0) angle = ANGLE_PI; return angle; } else if (dx == 0) { - angle = ANGLE_2PI; + angle = ANGLE_PI2; if (dy < 0) - angle = - ANGLE_2PI; + angle = - ANGLE_PI2; return angle; } angle = 0; if (dx < 0) { dx = -dx; dy = -dy; angle = ANGLE_PI; } if (dy < 0) { int tmp = dx; dx = -dy; dy = tmp; - angle = - ANGLE_2PI; + angle -= ANGLE_PI2; } if (dx == 0 && dy == 0) return 0; + if (dx == dy) - angle += ANGLE_4PI; + angle += ANGLE_PI4; else if (dx > dy) - angle += ATAN[Fixed.div(dy, dx) >> (26 - ATAN_BITS)]; + { + angle += ATAN[Fixed.div(dy, dx) << (ATAN_BITS - 6)]; + } else - angle += ANGLE_2PI - ATAN[Fixed.div(dx, dy) >> (26 - ATAN_BITS)]; + { + angle += ANGLE_PI2 - ATAN[Fixed.div(dx, dy) << (ATAN_BITS - 6)]; + } - if (angle > Math.PI) + if (angle > ANGLE_PI) angle -= ANGLE_2PI; return angle; } public static int angleDiff(int ang1, int ang2) { int delta = ang2 - ang1; delta %= ANGLE_2PI; if (delta < 0) delta += ANGLE_2PI; - if (delta > ANGLE_2PI) + if (delta > ANGLE_PI) delta -= ANGLE_2PI; return delta; } static void sort(int num, int[] array) { int swap; for (int i = 1; i < num; i++) { for (int j = i; j > 0; j--) { if (array[j] > array[j - 1]) break; swap = array[j]; array[j] = array[j - 1];