summaryrefslogtreecommitdiff
path: root/gnu/java/awt
diff options
context:
space:
mode:
authorRoman Kennke <roman@kennke.org>2006-12-15 00:59:45 +0000
committerRoman Kennke <roman@kennke.org>2006-12-15 00:59:45 +0000
commit6f814eed298d682410956a801a9d3e175326b8c3 (patch)
treee24a142c8ccf1f3d32ba48440f8b1be52a87601b /gnu/java/awt
parentf09e4046b6d9d19a58ddfe1f3bb9b72ec30aa89d (diff)
downloadclasspath-6f814eed298d682410956a801a9d3e175326b8c3.tar.gz
2006-12-14 Roman Kennke <kennke@aicas.com>
* 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.
Diffstat (limited to 'gnu/java/awt')
-rw-r--r--gnu/java/awt/font/autofit/AutoHinter.java7
-rw-r--r--gnu/java/awt/font/autofit/Edge.java5
-rw-r--r--gnu/java/awt/font/autofit/GlyphHints.java5
-rw-r--r--gnu/java/awt/font/autofit/HintScaler.java (renamed from gnu/java/awt/font/autofit/Scaler.java)5
-rw-r--r--gnu/java/awt/font/autofit/Latin.java203
-rw-r--r--gnu/java/awt/font/autofit/LatinAxis.java2
-rw-r--r--gnu/java/awt/font/autofit/LatinBlue.java5
-rw-r--r--gnu/java/awt/font/autofit/Script.java2
-rw-r--r--gnu/java/awt/font/autofit/ScriptMetrics.java4
-rw-r--r--gnu/java/awt/font/autofit/Utils.java34
-rw-r--r--gnu/java/awt/font/autofit/Width.java8
-rw-r--r--gnu/java/awt/font/opentype/truetype/Fixed.java13
-rw-r--r--gnu/java/awt/font/opentype/truetype/Zone.java3
13 files changed, 279 insertions, 17 deletions
diff --git a/gnu/java/awt/font/autofit/AutoHinter.java b/gnu/java/awt/font/autofit/AutoHinter.java
index 6f948e0cb..b61eaa182 100644
--- a/gnu/java/awt/font/autofit/AutoHinter.java
+++ b/gnu/java/awt/font/autofit/AutoHinter.java
@@ -40,6 +40,7 @@ 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;
/**
@@ -52,18 +53,24 @@ public class AutoHinter
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);
}
+
}
diff --git a/gnu/java/awt/font/autofit/Edge.java b/gnu/java/awt/font/autofit/Edge.java
index b71b2247c..8a19e55a4 100644
--- a/gnu/java/awt/font/autofit/Edge.java
+++ b/gnu/java/awt/font/autofit/Edge.java
@@ -48,6 +48,7 @@ class Edge
Edge serif;
int flags;
int dir;
+ Width blueEdge;
public String toString()
{
@@ -65,6 +66,10 @@ class Edge
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();
}
}
diff --git a/gnu/java/awt/font/autofit/GlyphHints.java b/gnu/java/awt/font/autofit/GlyphHints.java
index 8b20ea320..3f8229511 100644
--- a/gnu/java/awt/font/autofit/GlyphHints.java
+++ b/gnu/java/awt/font/autofit/GlyphHints.java
@@ -129,6 +129,11 @@ class GlyphHints
// 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.
diff --git a/gnu/java/awt/font/autofit/Scaler.java b/gnu/java/awt/font/autofit/HintScaler.java
index 105185125..01276b4db 100644
--- a/gnu/java/awt/font/autofit/Scaler.java
+++ b/gnu/java/awt/font/autofit/HintScaler.java
@@ -40,7 +40,7 @@ package gnu.java.awt.font.autofit;
import gnu.java.awt.font.opentype.OpenTypeFont;
-class Scaler
+class HintScaler
{
int xScale;
@@ -48,5 +48,6 @@ class Scaler
int yScale;
int yDelta;
OpenTypeFont face;
-
+ int renderMode;
+
}
diff --git a/gnu/java/awt/font/autofit/Latin.java b/gnu/java/awt/font/autofit/Latin.java
index 4587d987e..d836b99b3 100644
--- a/gnu/java/awt/font/autofit/Latin.java
+++ b/gnu/java/awt/font/autofit/Latin.java
@@ -172,10 +172,119 @@ class Latin
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;
+ }
+ }
+ }
}
/**
@@ -196,7 +305,7 @@ class Latin
// 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;
@@ -224,6 +333,8 @@ class Latin
}
touched.add(seg);
}
+ Utils.sort(numWidths, axis.widths);
+ axis.widthCount = numWidths;
}
for (int dim = 0; dim < DIMENSION_MAX; dim++)
{
@@ -638,11 +749,10 @@ class Latin
// 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];
@@ -667,7 +777,7 @@ class Latin
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;
}
@@ -780,6 +890,83 @@ class Latin
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);
+ }
+ }
}
}
diff --git a/gnu/java/awt/font/autofit/LatinAxis.java b/gnu/java/awt/font/autofit/LatinAxis.java
index a720cd93c..9237d0ee5 100644
--- a/gnu/java/awt/font/autofit/LatinAxis.java
+++ b/gnu/java/awt/font/autofit/LatinAxis.java
@@ -52,6 +52,8 @@ class LatinAxis
int edgeDistanceTreshold;
LatinBlue[] blues;
int blueCount;
+ int orgDelta;
+ int orgScale;
LatinAxis()
{
widths = new Width[Latin.MAX_WIDTHS];
diff --git a/gnu/java/awt/font/autofit/LatinBlue.java b/gnu/java/awt/font/autofit/LatinBlue.java
index 57143b065..694fb24fe 100644
--- a/gnu/java/awt/font/autofit/LatinBlue.java
+++ b/gnu/java/awt/font/autofit/LatinBlue.java
@@ -40,8 +40,9 @@ 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;
diff --git a/gnu/java/awt/font/autofit/Script.java b/gnu/java/awt/font/autofit/Script.java
index d394ff2e6..c223f0a26 100644
--- a/gnu/java/awt/font/autofit/Script.java
+++ b/gnu/java/awt/font/autofit/Script.java
@@ -52,7 +52,7 @@ interface Script
*/
void initMetrics(ScriptMetrics metrics, OpenTypeFont face);
- void scaleMetrics(ScriptMetrics metrics/* , scaler, map this */);
+ void scaleMetrics(ScriptMetrics metrics , HintScaler scaler);
void doneMetrics(ScriptMetrics metrics);
diff --git a/gnu/java/awt/font/autofit/ScriptMetrics.java b/gnu/java/awt/font/autofit/ScriptMetrics.java
index 6ec5d33f5..984a06dae 100644
--- a/gnu/java/awt/font/autofit/ScriptMetrics.java
+++ b/gnu/java/awt/font/autofit/ScriptMetrics.java
@@ -45,9 +45,9 @@ class ScriptMetrics
{
Script script;
- Scaler scaler;
+ HintScaler scaler;
ScriptMetrics()
{
- scaler = new Scaler();
+ scaler = new HintScaler();
}
}
diff --git a/gnu/java/awt/font/autofit/Utils.java b/gnu/java/awt/font/autofit/Utils.java
index bf093ba92..1b68ea791 100644
--- a/gnu/java/awt/font/autofit/Utils.java
+++ b/gnu/java/awt/font/autofit/Utils.java
@@ -212,4 +212,38 @@ class Utils
}
}
}
+
+ 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;
+ }
+
}
diff --git a/gnu/java/awt/font/autofit/Width.java b/gnu/java/awt/font/autofit/Width.java
index 0a2f0602b..15a344b63 100644
--- a/gnu/java/awt/font/autofit/Width.java
+++ b/gnu/java/awt/font/autofit/Width.java
@@ -47,4 +47,12 @@ public class Width
{
org = dist;
}
+
+ public String toString()
+ {
+ StringBuilder s = new StringBuilder();
+ s.append("[Width] org: ");
+ s.append(org);
+ return s.toString();
+ }
}
diff --git a/gnu/java/awt/font/opentype/truetype/Fixed.java b/gnu/java/awt/font/opentype/truetype/Fixed.java
index 03a8a87cf..4e1ba441e 100644
--- a/gnu/java/awt/font/opentype/truetype/Fixed.java
+++ b/gnu/java/awt/font/opentype/truetype/Fixed.java
@@ -69,14 +69,21 @@ public final class Fixed
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;
@@ -138,6 +145,10 @@ public final class Fixed
return (int) (d * 64);
}
+ public static int valueOf16(double d)
+ {
+ return (int) (d * (1 << 16));
+ }
/**
* Makes a string representation of a fixed-point number.
diff --git a/gnu/java/awt/font/opentype/truetype/Zone.java b/gnu/java/awt/font/opentype/truetype/Zone.java
index 8ce9a0c4f..63b1aa626 100644
--- a/gnu/java/awt/font/opentype/truetype/Zone.java
+++ b/gnu/java/awt/font/opentype/truetype/Zone.java
@@ -50,6 +50,8 @@ public final class Zone
private Point[] points;
private int numPoints;
+ public double scaleX, scaleY, shearX, shearY;
+
public Zone(int maxNumPoints)
{
points = new Point[maxNumPoints];
@@ -160,7 +162,6 @@ public final class Zone
void transform(double pointSize, AffineTransform deviceTransform,
int unitsPerEm, int preTranslateX, int preTranslateY)
{
- double scaleX, scaleY, shearX, shearY;
double factor;
factor = pointSize / (double) unitsPerEm;