You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-dev@xmlgraphics.apache.org by de...@apache.org on 2003/05/08 13:39:13 UTC
cvs commit: xml-batik/sources/org/apache/batik/gvt/text GlyphLayout.java
deweese 2003/05/08 04:39:13
Modified: samples/tests/spec/painting text-rendering.svg
sources/org/apache/batik/bridge CSSUtilities.java
sources/org/apache/batik/gvt/font AWTGVTGlyphVector.java
sources/org/apache/batik/gvt/renderer BasicTextPainter.java
StrokingTextPainter.java
sources/org/apache/batik/gvt/text GlyphLayout.java
Log:
With JDK 1.4 text-rendering="optimizeSpeed" will render
non-anti-aliased hinted text (for axially aligned text).
Revision Changes Path
1.3 +16 -9 xml-batik/samples/tests/spec/painting/text-rendering.svg
Index: text-rendering.svg
===================================================================
RCS file: /home/cvs/xml-batik/samples/tests/spec/painting/text-rendering.svg,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- text-rendering.svg 20 Nov 2001 15:08:25 -0000 1.2
+++ text-rendering.svg 8 May 2003 11:39:12 -0000 1.3
@@ -32,17 +32,24 @@
<g style="text-anchor:middle;font-size:64;font-weight:bold;fill:gold;stroke:crimson;stroke-width:2">
- <text x="120" y="180" style="text-rendering:auto">Batik</text>
- <text x="330" y="180" style="text-rendering:optimizeSpeed">Batik</text>
- <text x="120" y="330" style="text-rendering:optimizeLegibility">Batik</text>
- <text x="330" y="330" style="text-rendering:geometricPrecision">Batik</text>
+ <text x="120" y="130" style="text-rendering:auto">Batik</text>
+ <text x="330" y="130" style="text-rendering:optimizeSpeed">Batik</text>
+ <text x="120" y="280" style="text-rendering:optimizeLegibility">Batik</text>
+ <text x="330" y="280" style="text-rendering:geometricPrecision">Batik</text>
+ </g>
+
+ <g style="text-anchor:middle;font-size:64;font-weight:bold;fill:crimson">
+ <text x="120" y="200" text-rendering="auto" >Batik</text>
+ <text x="330" y="200" text-rendering="optimizeSpeed" >Batik</text>
+ <text x="120" y="350" text-rendering="optimizeLegibility">Batik</text>
+ <text x="330" y="350" text-rendering="geometricPrecision">Batik</text>
</g>
<g style="font-size:11;fill:black;stroke:none;text-anchor:middle">
- <text x="120" y="204">auto</text>
- <text x="330" y="204">optimizeSpeed</text>
- <text x="120" y="354">optimizeLegibility</text>
- <text x="330" y="354">geometricPrecision</text>
+ <text x="120" y="224" text-rendering="auto" >auto</text>
+ <text x="330" y="224" text-rendering="optimizeSpeed" >optimizeSpeed</text>
+ <text x="120" y="374" text-rendering="optimizeLegibility">optimizeLegibility</text>
+ <text x="330" y="374" text-rendering="geometricPrecision">geometricPrecision</text>
</g>
</g>
1.42 +8 -8 xml-batik/sources/org/apache/batik/bridge/CSSUtilities.java
Index: CSSUtilities.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/CSSUtilities.java,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -r1.41 -r1.42
--- CSSUtilities.java 11 Apr 2003 13:54:42 -0000 1.41
+++ CSSUtilities.java 8 May 2003 11:39:12 -0000 1.42
@@ -385,26 +385,26 @@
RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
hints.put(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_OFF);
- hints.put(RenderingHints.KEY_FRACTIONALMETRICS,
- RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
+ // hints.put(RenderingHints.KEY_FRACTIONALMETRICS,
+ // RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
break;
case 'l': // optimizeLegibility
hints.put(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
hints.put(RenderingHints.KEY_TEXT_ANTIALIASING,
- RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+ RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
hints.put(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
- hints.put(RenderingHints.KEY_FRACTIONALMETRICS,
- RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
+ // hints.put(RenderingHints.KEY_FRACTIONALMETRICS,
+ // RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
break;
case 'c': // geometricPrecision
hints.put(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
hints.put(RenderingHints.KEY_TEXT_ANTIALIASING,
- RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);
+ RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
hints.put(RenderingHints.KEY_ANTIALIASING,
- RenderingHints.VALUE_ANTIALIAS_DEFAULT);
+ RenderingHints.VALUE_ANTIALIAS_ON);
hints.put(RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_ON);
break;
1.22 +101 -10 xml-batik/sources/org/apache/batik/gvt/font/AWTGVTGlyphVector.java
Index: AWTGVTGlyphVector.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/font/AWTGVTGlyphVector.java,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -r1.21 -r1.22
--- AWTGVTGlyphVector.java 11 Apr 2003 13:58:43 -0000 1.21
+++ AWTGVTGlyphVector.java 8 May 2003 11:39:12 -0000 1.22
@@ -472,15 +472,19 @@
}
private static final boolean outlinesPositioned;
+ private static final boolean glyphVectorTransformWorks;
static {
String s = System.getProperty("java.specification.version");
if ("1.4".compareTo(s) <= 0) {
outlinesPositioned = true;
+ glyphVectorTransformWorks = true;
} else if ("Mac OS X".equals(System.getProperty("os.name"))) {
outlinesPositioned = true;
+ glyphVectorTransformWorks = false; // Note sure about this...
} else {
outlinesPositioned = false;
+ glyphVectorTransformWorks = false;
}
}
@@ -743,26 +747,113 @@
*/
public void draw(Graphics2D graphics2D,
AttributedCharacterIterator aci) {
+ int numGlyphs = getNumGlyphs();
aci.first();
+ Paint fillPaint = (Paint)aci.getAttribute(TextAttribute.FOREGROUND);
+ Stroke stroke = (Stroke) aci.getAttribute
+ (GVTAttributedCharacterIterator.TextAttribute.STROKE);
+ Paint strokePaint = (Paint) aci.getAttribute
+ (GVTAttributedCharacterIterator.TextAttribute.STROKE_PAINT);
+ if ((fillPaint == null) && ((strokePaint == null) ||
+ (stroke == null)))
+ return;
+
+ boolean useHinting = true;
+ if ((stroke != null) && (strokePaint != null))
+ useHinting = false;
+
+ final int typeGRot = AffineTransform.TYPE_GENERAL_ROTATION;
+ final int typeGTrans = AffineTransform.TYPE_GENERAL_TRANSFORM;
+ if (useHinting) {
+ // Check if usr->dev transform has general rotation,
+ // or shear..
+ AffineTransform at = graphics2D.getTransform();
+ int type = at.getType();
+ if (((type & typeGTrans) != 0) || ((type & typeGRot) != 0))
+ useHinting = false;
+ }
+
+ if (useHinting) {
+ double [] mat = new double[4];
+ for (int i=0; i<numGlyphs; i++) {
+ if (!glyphVisible[i]) {
+ useHinting = false;
+ break;
+ }
+ AffineTransform at = glyphTransforms[i];
+ if (at != null) {
+ int type = at.getType();
+ if ((type & ~AffineTransform.TYPE_TRANSLATION) == 0) {
+ // Just translation
+ } else if (glyphVectorTransformWorks &&
+ ((type & typeGTrans) == 0) &&
+ ((type & typeGRot) == 0)) {
+ // It's a simple 90Deg rotate, and we can put
+ // it into the GlyphVector.
+ } else {
+ // we can't (or it doesn't make sense
+ // to use the GlyphVector.
+ useHinting = false;
+ break;
+ }
+ }
+ }
+ }
+
+ if (useHinting) {
+ double sf = scaleFactor;
+ double [] mat = new double[6];
+ for (int i=0; i< numGlyphs; i++) {
+ Point2D pos = glyphPositions[i];
+ double x = pos.getX();
+ double y = pos.getY();
+ AffineTransform at = glyphTransforms[i];
+ if (at != null) {
+ // Scale the translate portion of matrix,
+ // and add it into the position.
+ at.getMatrix(mat);
+ x += mat[4];
+ y += mat[5];
+ if ((mat[0] != 1) || (mat[1] != 0) ||
+ (mat[2] != 0) || (mat[3] != 1)) {
+ // More than just translation.
+ mat[4] = 0; mat[5] = 0;
+ at = new AffineTransform(mat);
+ } else {
+ at = null;
+ }
+ }
+ pos = new Point2D.Double(x/sf, y/sf);
+ awtGlyphVector.setGlyphPosition(i, pos);
+ awtGlyphVector.setGlyphTransform(i, at);
+ }
+ graphics2D.scale(sf, sf);
+ graphics2D.setPaint(fillPaint);
+ graphics2D.drawGlyphVector(awtGlyphVector, 0, 0);
+ graphics2D.scale(1/sf, 1/sf);
+
+ for (int i=0; i< numGlyphs; i++) {
+ Point2D pos = defaultGlyphPositions[i];
+ awtGlyphVector.setGlyphPosition(i, pos);
+ awtGlyphVector.setGlyphTransform(i, null);
+ }
+
+ } else {
Shape outline = getOutline();
// check if we need to fill this glyph
- Paint paint = (Paint) aci.getAttribute(TextAttribute.FOREGROUND);
- if (paint != null) {
- graphics2D.setPaint(paint);
+ if (fillPaint != null) {
+ graphics2D.setPaint(fillPaint);
graphics2D.fill(outline);
}
// check if we need to draw the outline of this glyph
- Stroke stroke = (Stroke) aci.getAttribute
- (GVTAttributedCharacterIterator.TextAttribute.STROKE);
- paint = (Paint) aci.getAttribute
- (GVTAttributedCharacterIterator.TextAttribute.STROKE_PAINT);
- if (stroke != null && paint != null) {
+ if (stroke != null && strokePaint != null) {
graphics2D.setStroke(stroke);
- graphics2D.setPaint(paint);
+ graphics2D.setPaint(strokePaint);
graphics2D.draw(outline);
+ }
}
}
}
1.15 +4 -1 xml-batik/sources/org/apache/batik/gvt/renderer/BasicTextPainter.java
Index: BasicTextPainter.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/renderer/BasicTextPainter.java,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- BasicTextPainter.java 11 Apr 2003 13:58:44 -0000 1.14
+++ BasicTextPainter.java 8 May 2003 11:39:12 -0000 1.15
@@ -40,6 +40,9 @@
protected FontRenderContext fontRenderContext =
new FontRenderContext(new AffineTransform(), true, true);
+ protected FontRenderContext aaOffFontRenderContext =
+ new FontRenderContext(new AffineTransform(), false, true);
+
protected TextLayoutFactory getTextLayoutFactory() {
return textLayoutFactory;
}
1.44 +17 -2 xml-batik/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java
Index: StrokingTextPainter.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java,v
retrieving revision 1.43
retrieving revision 1.44
diff -u -r1.43 -r1.44
--- StrokingTextPainter.java 11 Apr 2003 13:58:44 -0000 1.43
+++ StrokingTextPainter.java 8 May 2003 11:39:12 -0000 1.44
@@ -11,8 +11,10 @@
import java.awt.Composite;
import java.awt.Graphics2D;
import java.awt.Paint;
+import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
+import java.awt.font.FontRenderContext;
import java.awt.font.TextAttribute;
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
@@ -624,8 +626,21 @@
subCharMap[i] = charMap[i+start-begin];
}
+ FontRenderContext frc = fontRenderContext;
+ RenderingHints rh = node.getRenderingHints();
+ // Check for optimizeSpeed, optimizeLegibility
+ // in these cases setup hintedFRC
+ if ((rh != null) &&
+ (rh.get(RenderingHints.KEY_TEXT_ANTIALIASING) ==
+ RenderingHints.VALUE_TEXT_ANTIALIAS_OFF)) {
+ // In both these cases we want the non-antialiased
+ // font render context.
+ frc = aaOffFontRenderContext;
+ }
+
layout = getTextLayoutFactory().createTextLayout
- (runaci, subCharMap, offset, fontRenderContext);
+ (runaci, subCharMap, offset, frc);
+
textRuns.add(new TextRun(layout, runaci, isChunkStart));
// System.out.println("TextRun: " + start + "->" + end +
// " Start: " + isChunkStart);
1.52 +18 -4 xml-batik/sources/org/apache/batik/gvt/text/GlyphLayout.java
Index: GlyphLayout.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/text/GlyphLayout.java,v
retrieving revision 1.51
retrieving revision 1.52
diff -u -r1.51 -r1.52
--- GlyphLayout.java 11 Apr 2003 13:58:48 -0000 1.51
+++ GlyphLayout.java 8 May 2003 11:39:13 -0000 1.52
@@ -644,8 +644,10 @@
return shape;
}
-
public static final float eps = 0.00001f;
+ public static boolean epsEQ(double a, double b) {
+ return ((a+eps > b) && (a-eps < b));
+ }
public static int makeConvexHull(Point2D.Float [] pts, int numPts) {
// Sort the Pts in X...
@@ -1312,12 +1314,24 @@
}
// rotate the glyph
- if (glyphRotation != 0f) {
+ if (!epsEQ(glyphRotation,0)) {
AffineTransform glyphTransform = gv.getGlyphTransform(i);
if (glyphTransform == null) {
glyphTransform = new AffineTransform();
}
- glyphTransform.rotate(glyphRotation);
+ AffineTransform rotAt;
+ // Make the 90Deg rotations slightly 'snap to'.
+ // Also use explicit matrix to avoid round-off.
+ if (epsEQ(glyphRotation, Math.PI/2)) {
+ rotAt = new AffineTransform(0, 1, -1, 0, 0, 0);
+ } else if (epsEQ(glyphRotation, Math.PI)) {
+ rotAt = new AffineTransform(-1, 0, 0, -1, 0, 0);
+ } else if (epsEQ(glyphRotation, 3*Math.PI/2)) {
+ rotAt = new AffineTransform(0, -1, 1, 0, 0, 0);
+ } else {
+ rotAt = AffineTransform.getRotateInstance(glyphRotation);
+ }
+ glyphTransform.concatenate(rotAt);
gv.setGlyphTransform(i, glyphTransform);
}
---------------------------------------------------------------------
To unsubscribe, e-mail: batik-dev-unsubscribe@xml.apache.org
For additional commands, e-mail: batik-dev-help@xml.apache.org