This implements the detection of blue edges. These are edges of a glyph
outline that are associated with a certain blue zone. (Later on, these
edges get moved to match that zone, etc).
This also implements/fixes the scaling in the autohinter.
2006-12-14 Roman Kennke <[EMAIL PROTECTED]>
* gnu/java/awt/font/autofit/HintScaler.java
Renamed Scaler to HintScaler to avoid name-clash.
* gnu/java/awt/font/autofit/AutoHinter.java
(scaler): New field.
(applyHints): Scale the metrics before applying the hints.
(init): Copy font into scaler.
* gnu/java/awt/font/autofit/Edge.java
(blueEdge): New field.
(toString): Include first and last fields in debug output.
* gnu/java/awt/font/autofit/GlyphHints.java
(reload): Grab the scales here.
* gnu/java/awt/font/autofit/Latin.java
(computeBlueEdges): Implemented blue-edge detection.
(computeEdges): Correctly calculate edgeDistanceThreshold and
the scaled edge position.
(initWidths): Renamed Scaler to HintScaler. Sort widths and
store widthCount.
(scaleMetrics): Add HintScaler parameter. Implemented to scale
the metrics.
(scaleMetricsDim): New helper method.
* gnu/java/awt/font/autofit/LatinAxis.java
(orgDelta): New field.
(orgScale): New field.
* gnu/java/awt/font/autofit/LatinBlue.java: Reordered flags.
(FLAG_BLUE_ACTIVE): New flag.
* gnu/java/awt/font/autofit/Scaler.java: Renamed to HintScaler.
* gnu/java/awt/font/autofit/Script.java
(scaleMetrics): Add HintScaler argument.
* gnu/java/awt/font/autofit/ScriptMetrics.java
Renamed Scaler to HintScaler.
* gnu/java/awt/font/autofit/Utils.java
(sort(int,Width[])): New helper method. Sorts Width arrays.
(mulDiv): New helper method.
(pixFloor): New helper method.
(pixRound): New helper method.
* gnu/java/awt/font/autofit/Width.java
(toString): New method. For debug output.
* gnu/java/awt/font/opentype/truetype/Fixed.java
(mul16): New method. Multiplies with 16.16 fixed point arithmetics.
(div16): New method. Divides with 16.16 fixed point arithmetics.
(valueOf16): New method. Converts double to 16.16 fixed point.
* gnu/java/awt/font/opentype/truetype/Zone.java
(scaleX): New field.
(scaleY): New field.
(shearX): New field.
(shearY): New field.
(transform): Store translation and shearing in fields instead of
local vars.
/Roman
Index: gnu/java/awt/font/autofit/AutoHinter.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/font/autofit/AutoHinter.java,v
retrieving revision 1.2
diff -u -1 -5 -r1.2 AutoHinter.java
--- gnu/java/awt/font/autofit/AutoHinter.java 14 Dec 2006 20:32:54 -0000 1.2
+++ gnu/java/awt/font/autofit/AutoHinter.java 15 Dec 2006 00:58:48 -0000
@@ -28,42 +28,49 @@
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.awt.font.autofit;
import gnu.java.awt.font.opentype.Hinter;
import gnu.java.awt.font.opentype.OpenTypeFont;
+import gnu.java.awt.font.opentype.truetype.Fixed;
import gnu.java.awt.font.opentype.truetype.Zone;
/**
* The public interface to the automatic gridfitter.
*/
public class AutoHinter
implements Hinter
{
Latin latinScript;
LatinMetrics metrics;
GlyphHints hints;
+ HintScaler scaler = new HintScaler();
public void init(OpenTypeFont font)
{
// TODO: Should support other scripts too.
latinScript = new Latin();
metrics = new LatinMetrics(font);
latinScript.initMetrics(metrics, font);
+ scaler.face = font;
}
public void applyHints(Zone outline)
{
if (hints == null)
hints = new GlyphHints();
+ scaler.xScale = Fixed.valueOf16(outline.scaleX * 64);
+ scaler.yScale = Fixed.valueOf16(outline.scaleY * 64);
+ latinScript.scaleMetrics(metrics, scaler);
latinScript.applyHints(hints, outline, metrics);
}
+
}
Index: gnu/java/awt/font/autofit/Edge.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/font/autofit/Edge.java,v
retrieving revision 1.1
diff -u -1 -5 -r1.1 Edge.java
--- gnu/java/awt/font/autofit/Edge.java 14 Dec 2006 20:32:54 -0000 1.1
+++ gnu/java/awt/font/autofit/Edge.java 15 Dec 2006 00:58:48 -0000
@@ -36,35 +36,40 @@
exception statement from your version. */
package gnu.java.awt.font.autofit;
class Edge
{
int fpos;
Segment first;
Segment last;
int opos;
Edge link;
Edge serif;
int flags;
int dir;
+ Width blueEdge;
public String toString()
{
StringBuilder s = new StringBuilder();
s.append("[Edge] id");
s.append(hashCode());
s.append(", fpos: ");
s.append(fpos);
s.append(", opos: ");
s.append(opos);
s.append(", dir: ");
s.append(dir);
s.append(", serif: ");
s.append(serif != null ? serif.hashCode() : "null");
s.append(", link: ");
s.append(link != null ? link.hashCode() : "null");
s.append(", flags: " + flags);
+ s.append(", first: ");
+ s.append(first.hashCode());
+ s.append(", last: ");
+ s.append(last.hashCode());
return s.toString();
}
}
Index: gnu/java/awt/font/autofit/GlyphHints.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/font/autofit/GlyphHints.java,v
retrieving revision 1.3
diff -u -1 -5 -r1.3 GlyphHints.java
--- gnu/java/awt/font/autofit/GlyphHints.java 14 Dec 2006 20:32:54 -0000 1.3
+++ gnu/java/awt/font/autofit/GlyphHints.java 15 Dec 2006 00:58:48 -0000
@@ -117,30 +117,35 @@
System.arraycopy(points, 0, newPoints, 0, maxPoints);
}
points = newPoints;
maxPoints = newMax;
}
numPoints = outline.getSize() - 4; // 4 phantom points.
numContours = outline.getNumContours();
// Set major direction. We don't handle Type 1 fonts yet.
axis[DIMENSION_HORZ].majorDir = DIR_UP;
axis[DIMENSION_VERT].majorDir = DIR_LEFT;
// TODO: Freetype seems to scale and translate the glyph at that point.
// I suppose that this is not really needed.
+ // The scales are scaling from font units to 1/64 device pixels.
+ xScale = Fixed.valueOf16(outline.scaleX * 64);
+ yScale = Fixed.valueOf16(outline.scaleY * 64);
+
+ // FIXME: What is that xDelta and yDelta used for?
System.arraycopy(outline.getPoints(), 0, points, 0, numPoints);
// Setup prev and next and contours array.
// TODO: Probably cache this.
contours = new Point[numContours];
Point currentContour = points[0];
for (int i = 0, cIndex = 0; i < numPoints; i++)
{
// Start new contour when the last point has been a contour end.
if (outline.isContourEnd(i))
{
// Connect the contour end point to the start point.
points[i].setNext(currentContour);
currentContour.setPrev(points[i]);
contours[cIndex] = currentContour;
Index: gnu/java/awt/font/autofit/HintScaler.java
===================================================================
RCS file: gnu/java/awt/font/autofit/HintScaler.java
diff -N gnu/java/awt/font/autofit/HintScaler.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gnu/java/awt/font/autofit/HintScaler.java 15 Dec 2006 00:58:48 -0000
@@ -0,0 +1,53 @@
+/* Scaler.java -- FIXME: briefly describe file purpose
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.font.autofit;
+
+import gnu.java.awt.font.opentype.OpenTypeFont;
+
+class HintScaler
+{
+
+ int xScale;
+ int xDelta;
+ int yScale;
+ int yDelta;
+ OpenTypeFont face;
+ int renderMode;
+
+}
Index: gnu/java/awt/font/autofit/Latin.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/font/autofit/Latin.java,v
retrieving revision 1.4
diff -u -1 -5 -r1.4 Latin.java
--- gnu/java/awt/font/autofit/Latin.java 14 Dec 2006 20:32:54 -0000 1.4
+++ gnu/java/awt/font/autofit/Latin.java 15 Dec 2006 00:58:48 -0000
@@ -160,82 +160,193 @@
* @param metrics the script metrics to initialize
* @param face the font
*/
public void initMetrics(ScriptMetrics metrics, OpenTypeFont face)
{
assert metrics instanceof LatinMetrics;
LatinMetrics lm = (LatinMetrics) metrics;
lm.unitsPerEm = face.unitsPerEm;
// TODO: Check for latin charmap.
initWidths(lm, face, 'o');
initBlues(lm, face);
}
- public void scaleMetrics(ScriptMetrics metrics)
+ public void scaleMetrics(ScriptMetrics metrics, HintScaler scaler)
{
- // TODO Auto-generated method stub
+ LatinMetrics lm = (LatinMetrics) metrics;
+ lm.scaler.renderMode = scaler.renderMode;
+ lm.scaler.face = scaler.face;
+ scaleMetricsDim(lm, scaler, DIMENSION_HORZ);
+ scaleMetricsDim(lm, scaler, DIMENSION_VERT);
+ }
+ private void scaleMetricsDim(LatinMetrics lm, HintScaler scaler, int dim)
+ {
+ int scale;
+ int delta;
+ if (dim == DIMENSION_HORZ)
+ {
+ scale = scaler.xScale;
+ delta = scaler.xDelta;
+ }
+ else
+ {
+ scale = scaler.yScale;
+ delta = scaler.yDelta;
+ }
+ LatinAxis axis = lm.axis[dim];
+ if (axis.orgScale == scale && axis.orgDelta == delta)
+ // No change, no need to adjust.
+ return;
+ axis.orgScale = scale;
+ axis.orgDelta = delta;
+
+ // Correct X and Y scale to optimize the alignment of the top small
+ // letters to the pixel grid.
+ LatinAxis axis2 = lm.axis[DIMENSION_VERT];
+ LatinBlue blue = null;
+ for (int nn = 0; nn < axis2.blueCount; nn++)
+ {
+ if ((axis2.blues[nn].flags & LatinBlue.FLAG_ADJUSTMENT) != 0)
+ {
+ blue = axis2.blues[nn];
+ break;
+ }
+ }
+ if (blue != null)
+ {
+ int scaled = Fixed.mul16(blue.shoot.org, scaler.yScale);
+ int fitted = Utils.pixRound(scaled);
+ if (scaled != fitted)
+ {
+ if (dim == DIMENSION_HORZ)
+ {
+ if (fitted < scaled)
+ {
+ scale -= scale / 50;
+ }
+ }
+ else
+ {
+ scale = Utils.mulDiv(scale, fitted, scaled);
+ }
+ }
+ }
+ axis.scale = scale;
+ axis.delta = delta;
+ if (dim == DIMENSION_HORZ)
+ {
+ lm.scaler.xScale = scale;
+ lm.scaler.xDelta = delta;
+ }
+ else
+ {
+ lm.scaler.yScale = scale;
+ lm.scaler.yDelta = delta;
+ }
+ // Scale the standard widths.
+ for (int nn = 0; nn < axis.widthCount; nn++)
+ {
+ Width w = axis.widths[nn];
+ w.cur = Fixed.mul16(w.org, scale);
+ w.fit = w.cur;
+ }
+ // Scale blue zones.
+ if (dim == DIMENSION_VERT)
+ {
+ for (int nn = 0; nn < axis.blueCount; nn++)
+ {
+ blue = axis.blues[nn];
+ blue.ref.cur = Fixed.mul16(blue.ref.org, scale) + delta;
+ blue.ref.fit = blue.ref.cur;
+ blue.shoot.cur = Fixed.mul16(blue.ref.org, scale) + delta;
+ blue.flags &= ~LatinBlue.FLAG_BLUE_ACTIVE;
+ // A blue zone is only active if it is less than 3/4 pixels tall.
+ int dist = Fixed.mul16(blue.ref.org - blue.shoot.org, scale);
+ if (dist <= 48 && dist >= -48)
+ {
+ int delta1 = blue.shoot.org - blue.ref.org;
+ int delta2 = delta1;
+ if (delta1 < 0)
+ delta2 = -delta2;
+ delta2 = Fixed.mul16(delta2, scale);
+ if (delta2 < 32)
+ delta2 = 0;
+ else if (delta2 < 64)
+ delta2 = 32 + (((delta2 - 32) + 16) & ~31);
+ else
+ delta2 = Utils.pixRound(delta2);
+ if (delta1 < 0)
+ delta2 = -delta2;
+ blue.ref.fit = Utils.pixRound(blue.ref.cur);
+ blue.shoot.fit = blue.ref.fit+ delta2;
+ blue.flags |= LatinBlue.FLAG_BLUE_ACTIVE;
+ }
+ }
+ }
}
/**
* Determines the standard stem widths.
*
* @param metrics the metrics to use
* @param face the font face
* @param ch the character that is used for getting the widths
*/
private void initWidths(LatinMetrics metrics, OpenTypeFont face, char ch)
{
GlyphHints hints = new GlyphHints();
metrics.axis[DIMENSION_HORZ].widthCount = 0;
metrics.axis[DIMENSION_VERT].widthCount = 0;
int glyphIndex = face.getGlyph(ch);
// TODO: Avoid that AffineTransform constructor and change
// getRawGlyphOutline() to accept null or remove that parameter altogether.
// Consider this when the thing is done and we know what we need that for.
Zone outline = face.getRawGlyphOutline(glyphIndex, IDENTITY);
LatinMetrics dummy = new LatinMetrics();
- Scaler scaler = dummy.scaler;
+ HintScaler scaler = dummy.scaler;
dummy.unitsPerEm = metrics.unitsPerEm;
scaler.xScale = scaler.yScale = 10000;
scaler.xDelta = scaler.yDelta = 0;
scaler.face = face;
hints.rescale(dummy);
hints.reload(outline);
for (int dim = 0; dim < DIMENSION_MAX; dim++)
{
LatinAxis axis = metrics.axis[dim];
AxisHints axHints = hints.axis[dim];
int numWidths = 0;
computeSegments(hints, dim);
linkSegments(hints, dim);
Segment[] segs = axHints.segments;
HashSet<Segment> touched = new HashSet<Segment>();
for (int i = 0; i < segs.length; i++)
{
Segment seg = segs[i];
Segment link = seg.link;
if (link != null && link.link == seg && ! touched.contains(link))
{
int dist = Math.abs(seg.pos - link.pos);
if (numWidths < MAX_WIDTHS)
axis.widths[numWidths++] = new Width(dist);
}
touched.add(seg);
}
+ Utils.sort(numWidths, axis.widths);
+ axis.widthCount = numWidths;
}
for (int dim = 0; dim < DIMENSION_MAX; dim++)
{
LatinAxis axis = metrics.axis[dim];
int stdw = axis.widthCount > 0 ? axis.widths[0].org
: constant(metrics, 50);
axis.edgeDistanceTreshold= stdw / 5;
}
}
void linkSegments(GlyphHints hints, int dim)
{
AxisHints axis = hints.axis[dim];
Segment[] segments = axis.segments;
int numSegs = axis.numSegments;
@@ -626,60 +737,59 @@
scale = dim == DIMENSION_HORZ ? hints.xScale : hints.yScale;
upDir = dim == DIMENSION_HORZ ? DIR_UP : DIR_RIGHT;
// We will begin by generating a sorted table of edges for the
// current direction. To do so, we simply scan each segment and try
// to find an edge in our table that corresponds to its position.
//
// If no edge is found, we create one and insert a new edge in the
// sorted table. Otherwise, we simply add the segment to the egde's
// list which will be processed in the second step to compute the
// edge's properties.
//
// Note that the edge table is sorted along the segment/edge
// position.
- edgeDistanceThreshold = Fixed.mul(laxis.edgeDistanceTreshold, scale);
+ edgeDistanceThreshold = Fixed.mul16(laxis.edgeDistanceTreshold, scale);
if (edgeDistanceThreshold > 64 / 4)
edgeDistanceThreshold = 64 / 4;
- edgeDistanceThreshold = Fixed.div(edgeDistanceThreshold, scale);
-
+ edgeDistanceThreshold = Fixed.div16(edgeDistanceThreshold, scale);
for (int i = 0; i < numSegments; i++)
{
seg = segments[i];
Edge found = null;
for (int ee = 0; ee < axis.numEdges; ee++)
{
Edge edge = axis.edges[ee];
int dist = seg.pos - edge.fpos;
if (dist < 0)
dist = -dist;
if (dist < edgeDistanceThreshold)
{
found = edge;
break;
}
}
if (found == null)
{
// Insert new edge in the list and sort according to
// the position.
Edge edge = axis.newEdge(seg.pos);
edge.first = seg;
edge.last = seg;
edge.fpos = seg.pos;
- edge.opos = Fixed.mul(seg.pos, scale);
+ edge.opos = Fixed.mul16(seg.pos, scale);
seg.edgeNext = seg;
seg.edge = edge;
}
else
{
seg.edgeNext = found.first;
found.last.edgeNext = seg;
found.last = seg;
seg.edge = found;
}
}
// Good. We will now compute each edge's properties according to
// segments found on its position. Basically these are:
// - Edge's main direction.
// - Stem edge, serif edge, or both (which defaults to stem edge).
@@ -768,18 +878,95 @@
// Gets rid of serif if link is set. This gets rid of many
// unpleasant artifacts.
if (edge.serif != null && edge.link != null)
{
edge.serif = null;
}
// Debug: Print out all edges.
// System.err.println("edge# " + e + ": " + edge);
}
}
private void computeBlueEdges(GlyphHints hints, LatinMetrics metrics)
{
- // TODO: Implement.
+ AxisHints axis = hints.axis[DIMENSION_VERT];
+ Edge[] edges = axis.edges;
+ int numEdges = axis.numEdges;
+ LatinAxis latin = metrics.axis[DIMENSION_VERT];
+ int scale = latin.scale;
+
+ // Compute which blue zones are active. I.e. have their scaled
+ // size < 3/4 pixels.
+
+ // For each horizontal edge search the blue zone that is closest.
+ for (int e = 0; e < numEdges; e++)
+ {
+ Edge edge = edges[e];
+ // System.err.println("checking edge: " + edge);
+ Width bestBlue = null;
+ int bestDist = Fixed.mul16(metrics.unitsPerEm / 40, scale);
+
+ if (bestDist > 64 / 2)
+ bestDist = 64 / 2;
+ for (int bb = 0; bb < BLUE_MAX; bb++)
+ {
+ LatinBlue blue = latin.blues[bb];
+ // System.err.println("checking blue: " + blue);
+ // Skip inactive blue zones, i.e. those that are too small.
+ if ((blue.flags & LatinBlue.FLAG_BLUE_ACTIVE) == 0)
+ continue;
+ // If it is a top zone, check for right edges. If it is a bottom
+ // zone, check for left edges.
+ boolean isTopBlue = (blue.flags & LatinBlue.FLAG_TOP) != 0;
+ boolean isMajorDir = edge.dir == axis.majorDir;
+
+ // If it is a top zone, the edge must be against the major
+ // direction. If it is a bottom zone it must be in the major
+ // direction.
+ if (isTopBlue ^ isMajorDir)
+ {
+ int dist = edge.fpos - blue.ref.org;
+ if (dist < 0)
+ dist = -dist;
+ dist = Fixed.mul16(dist, scale);
+ if (dist < bestDist)
+ {
+ bestDist = dist;
+ bestBlue = blue.ref;
+ }
+
+ // Now, compare it to the overshoot position if the edge is
+ // rounded, and if the edge is over the reference position of
+ // a top zone, or under the reference position of a bottom
+ // zone.
+ if ((edge.flags & Segment.FLAG_EDGE_ROUND) != 0 && dist != 0)
+ {
+ // Inversed vertical coordinates!
+ boolean isUnderRef = edge.fpos > blue.ref.org;
+ if (isTopBlue ^ isUnderRef)
+ {
+ blue = latin.blues[bb]; // Needed?
+ dist = edge.fpos - blue.shoot.org;
+ if (dist < 0)
+ dist = -dist;
+ dist = Fixed.mul16(dist, scale);
+ if (dist < bestDist)
+ {
+ bestDist = dist;
+ bestBlue = blue.shoot;
+ }
+ }
+ }
+
+ }
+ }
+ if (bestBlue != null)
+ {
+ edge.blueEdge = bestBlue;
+ // Debug: Print out the blue edges.
+ // System.err.println("blue edge for: " + edge + ": " + bestBlue);
+ }
+ }
}
}
Index: gnu/java/awt/font/autofit/LatinAxis.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/font/autofit/LatinAxis.java,v
retrieving revision 1.4
diff -u -1 -5 -r1.4 LatinAxis.java
--- gnu/java/awt/font/autofit/LatinAxis.java 14 Dec 2006 20:32:54 -0000 1.4
+++ gnu/java/awt/font/autofit/LatinAxis.java 15 Dec 2006 00:58:48 -0000
@@ -40,21 +40,23 @@
/**
* Some axis specific data.
*/
class LatinAxis
{
int scale;
int delta;
int widthCount;
Width[] widths;
int edgeDistanceTreshold;
LatinBlue[] blues;
int blueCount;
+ int orgDelta;
+ int orgScale;
LatinAxis()
{
widths = new Width[Latin.MAX_WIDTHS];
blues = new LatinBlue[Latin.BLUE_MAX];
}
}
Index: gnu/java/awt/font/autofit/LatinBlue.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/font/autofit/LatinBlue.java,v
retrieving revision 1.1
diff -u -1 -5 -r1.1 LatinBlue.java
--- gnu/java/awt/font/autofit/LatinBlue.java 14 Dec 2006 19:07:19 -0000 1.1
+++ gnu/java/awt/font/autofit/LatinBlue.java 15 Dec 2006 00:58:48 -0000
@@ -28,31 +28,32 @@
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.awt.font.autofit;
public class LatinBlue
{
- static final int FLAG_TOP = 1;
- static final int FLAG_ADJUSTMENT = 1;
+ static final int FLAG_BLUE_ACTIVE = 1 << 0;
+ static final int FLAG_TOP = 1 << 1;
+ static final int FLAG_ADJUSTMENT = 1 << 2;
Width ref;
Width shoot;
int flags;
public String toString()
{
StringBuilder s = new StringBuilder();
s.append("[BlueZone]");
s.append(" ref: ");
s.append(ref.org);
s.append(", shoot: ");
s.append(shoot.org);
return s.toString();
}
}
Index: gnu/java/awt/font/autofit/Scaler.java
===================================================================
RCS file: gnu/java/awt/font/autofit/Scaler.java
diff -N gnu/java/awt/font/autofit/Scaler.java
--- gnu/java/awt/font/autofit/Scaler.java 14 Nov 2006 15:18:09 -0000 1.1
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,52 +0,0 @@
-/* Scaler.java -- FIXME: briefly describe file purpose
- Copyright (C) 2006 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.java.awt.font.autofit;
-
-import gnu.java.awt.font.opentype.OpenTypeFont;
-
-class Scaler
-{
-
- int xScale;
- int xDelta;
- int yScale;
- int yDelta;
- OpenTypeFont face;
-
-}
Index: gnu/java/awt/font/autofit/Script.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/font/autofit/Script.java,v
retrieving revision 1.2
diff -u -1 -5 -r1.2 Script.java
--- gnu/java/awt/font/autofit/Script.java 14 Dec 2006 20:32:54 -0000 1.2
+++ gnu/java/awt/font/autofit/Script.java 15 Dec 2006 00:58:48 -0000
@@ -40,23 +40,23 @@
import gnu.java.awt.font.opentype.OpenTypeFont;
import gnu.java.awt.font.opentype.truetype.Zone;
/**
* Defines script specific methods for the auto fitter.
*/
interface Script
{
/**
* Initializes the metrics.
*/
void initMetrics(ScriptMetrics metrics, OpenTypeFont face);
- void scaleMetrics(ScriptMetrics metrics/* , scaler, map this */);
+ void scaleMetrics(ScriptMetrics metrics , HintScaler scaler);
void doneMetrics(ScriptMetrics metrics);
void initHints(GlyphHints hints, ScriptMetrics metrics);
void applyHints(GlyphHints hints, Zone outline, ScriptMetrics metrics);
}
Index: gnu/java/awt/font/autofit/ScriptMetrics.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/font/autofit/ScriptMetrics.java,v
retrieving revision 1.2
diff -u -1 -5 -r1.2 ScriptMetrics.java
--- gnu/java/awt/font/autofit/ScriptMetrics.java 13 Dec 2006 22:59:43 -0000 1.2
+++ gnu/java/awt/font/autofit/ScriptMetrics.java 15 Dec 2006 00:58:48 -0000
@@ -33,21 +33,21 @@
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.awt.font.autofit;
/**
* Script specific metrics data.
*/
class ScriptMetrics
{
Script script;
- Scaler scaler;
+ HintScaler scaler;
ScriptMetrics()
{
- scaler = new Scaler();
+ scaler = new HintScaler();
}
}
Index: gnu/java/awt/font/autofit/Utils.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/font/autofit/Utils.java,v
retrieving revision 1.2
diff -u -1 -5 -r1.2 Utils.java
--- gnu/java/awt/font/autofit/Utils.java 14 Dec 2006 15:14:12 -0000 1.2
+++ gnu/java/awt/font/autofit/Utils.java 15 Dec 2006 00:58:48 -0000
@@ -200,16 +200,50 @@
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];
array[j - 1] = swap;
}
}
}
+
+ static void sort(int num, Width[] array)
+ {
+ Width swap;
+ for (int i = 1; i < num; i++)
+ {
+ for (int j = 1; j > 0; j--)
+ {
+ if (array[j].org > array[j - 1].org)
+ break;
+ swap = array[j];
+ array[j] = array[j - 1];
+ array[j - 1] = swap;
+ }
+ }
+ }
+
+ static int pixRound(int val)
+ {
+ return pixFloor(val + 32);
+ }
+
+ static int pixFloor(int val)
+ {
+ return val & ~63;
+ }
+
+ public static int mulDiv(int a, int b, int c)
+ {
+ long prod = a * b;
+ long div = (prod / c);
+ return (int) div;
+ }
+
}
Index: gnu/java/awt/font/autofit/Width.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/font/autofit/Width.java,v
retrieving revision 1.2
diff -u -1 -5 -r1.2 Width.java
--- gnu/java/awt/font/autofit/Width.java 13 Dec 2006 22:59:43 -0000 1.2
+++ gnu/java/awt/font/autofit/Width.java 15 Dec 2006 00:58:48 -0000
@@ -35,16 +35,24 @@
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.awt.font.autofit;
public class Width
{
int org;
int cur;
int fit;
Width(int dist)
{
org = dist;
}
+
+ public String toString()
+ {
+ StringBuilder s = new StringBuilder();
+ s.append("[Width] org: ");
+ s.append(org);
+ return s.toString();
+ }
}
Index: gnu/java/awt/font/opentype/truetype/Fixed.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/font/opentype/truetype/Fixed.java,v
retrieving revision 1.2
diff -u -1 -5 -r1.2 Fixed.java
--- gnu/java/awt/font/opentype/truetype/Fixed.java 13 Dec 2006 22:59:43 -0000 1.2
+++ gnu/java/awt/font/opentype/truetype/Fixed.java 15 Dec 2006 00:58:48 -0000
@@ -57,38 +57,45 @@
* The constructor is private so nobody can use it.
*/
private Fixed()
{
}
/**
* Multiplies two fixed-point numbers.
*/
public static int mul(int a, int b)
{
return (int) ((((long) a) * b) >> 6);
}
+ public static int mul16(int a, int b)
+ {
+ return (int) ((((long) a) * b) >> 16);
+ }
public static int div(int a, int b)
{
return (int) ((((long) a) << 6) / b);
}
+ public static int div16(int a, int b)
+ {
+ return (int) ((((long) a) << 16) / b);
+ }
-
public static int ceil(int a)
{
return (a + 63) & -64;
}
public static int floor(int a)
{
return a & -64;
}
/**
* Calculates the length of a fixed-point vector.
*/
@@ -126,30 +133,34 @@
return ((double) f) / 64;
}
public static int valueOf(float f)
{
return (int) (f * 64);
}
public static int valueOf(double d)
{
return (int) (d * 64);
}
+ public static int valueOf16(double d)
+ {
+ return (int) (d * (1 << 16));
+ }
/**
* Makes a string representation of a fixed-point number.
*/
public static String toString(int f)
{
return String.valueOf(floatValue(f));
}
public static String toString(int x, int y)
{
StringBuffer sbuf = new StringBuffer(40);
sbuf.append('(');
sbuf.append(((float) x) / 64);
Index: gnu/java/awt/font/opentype/truetype/Zone.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/font/opentype/truetype/Zone.java,v
retrieving revision 1.4
diff -u -1 -5 -r1.4 Zone.java
--- gnu/java/awt/font/opentype/truetype/Zone.java 14 Dec 2006 15:14:13 -0000 1.4
+++ gnu/java/awt/font/opentype/truetype/Zone.java 15 Dec 2006 00:58:48 -0000
@@ -38,30 +38,32 @@
package gnu.java.awt.font.opentype.truetype;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator;
/**
* A collection of points with some additional information.
*/
public final class Zone
{
private Point[] points;
private int numPoints;
+ public double scaleX, scaleY, shearX, shearY;
+
public Zone(int maxNumPoints)
{
points = new Point[maxNumPoints];
}
public int getCapacity()
{
return points.length;
}
public int getSize()
{
return numPoints;
}
@@ -148,31 +150,30 @@
public void setContourEnd(int point, boolean segEnd)
{
if (segEnd)
points[point].flags |= Point.FLAG_CONTOUR_END;
else
points[point].flags &= ~Point.FLAG_CONTOUR_END;
}
void transform(double pointSize, AffineTransform deviceTransform,
int unitsPerEm, int preTranslateX, int preTranslateY)
{
- double scaleX, scaleY, shearX, shearY;
double factor;
factor = pointSize / (double) unitsPerEm;
scaleX = deviceTransform.getScaleX() * factor;
scaleY = deviceTransform.getScaleY() * factor;
shearX = deviceTransform.getShearX() * factor;
shearY = deviceTransform.getShearY() * factor;
for (int i = 0; i < numPoints; i++)
{
int x = points[i].origX + preTranslateX;
int y = points[i].origY + preTranslateY;
points[i].scaledX = /*points[i].origX = */Fixed.valueOf(scaleX * x
+ shearX * y);