Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6479365

Combining negative scale and negative shear in Font Transform produced incorrect results in JDK 6

    XMLWordPrintable

Details

    • 2d
    • b77
    • 6
    • b03
    • x86
    • linux, windows_xp
    • Verified

    Backports

      Description

        FULL PRODUCT VERSION :
        java version "1.6.0-beta2"
        Java(TM) SE Runtime Environment (build 1.6.0-beta2-b86)
        Java HotSpot(TM) Client VM (build 1.6.0-beta2-b86, mixed mode, sharing)

        ADDITIONAL OS VERSION INFORMATION :
        Microsoft Windows XP [Version 5.1.2600]

        A DESCRIPTION OF THE PROBLEM :
        Results produced from the shear() operation do not match results produced in JDK 1.2 thru 1.5. shear() was used to produce a "inverted, slanted" font which looked like a shadow to the original font. The original font was flipped, then sheared which produced the shadow affect.

        fontTransform = AffineTransform.getScaleInstance(1.0, -1.0);
          fontTransform.shear(-1.0, 0.0);
        reflectionFont = textFont.deriveFont(fontTransform);

        Up through JDK 1.5, this produced a "shadow" of the original font, In JDK 1.6B2, the shear inverts the font across the Y axis instead of slanting the original font.

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        The following code was used to illustrate affine transforms and rendering hints in a class I teach. This code worked correctly until JDK 6.

        Sample code is included below that shows this behavior.

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        The generated font should appear below the original font, not to the left of the font.
        ACTUAL -
        The new "shadow" font is no longer correct. If you just scale the font, you get the correct results, if you just shear the font, you get the correct results, if you scale the font, then shear it, it appears as though axis values are flipped.

        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        import javax.swing.*;
        import java.awt.*;
        import java.awt.event.*;
        import java.awt.geom.*;

        public class Affine1 extends JPanel{
            // our arrow shape
            GeneralPath arrow = new GeneralPath();
            // rotate transform
            AffineTransform arrowRotate;
            // shadow transform
            AffineTransform shadowScale;
            // shear transform
            AffineTransform shadowShear;
            // font transform
            AffineTransform fontTransform;
            Shape rotatedArrow;
            Shape scaledArrow;
            Shape skewedArrow;
            static RenderingHints hints1;
            static RenderingHints hints2;
            Font textFont = new Font("Arial", Font.PLAIN, 40);
            // derived fonts...
            Font reflectionFont;
            Font reflectionFont2;

            public Affine1 () {
        super();
        setLayout(null);

        // get the graphics environment
        GraphicsEnvironment env =
        GraphicsEnvironment.getLocalGraphicsEnvironment();
        env.getAvailableFontFamilyNames();

        hints1 = new RenderingHints(RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);
        hints2 = new RenderingHints(RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_OFF);

        // build our arrow, but it is pointing to the right
        arrow.moveTo(0f, -10f);
        arrow.lineTo(20f, -10f);
        arrow.lineTo(20f, 0f);
        arrow.lineTo(40, -20f);
        arrow.lineTo(20f, -40f);
        arrow.lineTo(20f, -30f);
        arrow.lineTo(0f, -30f);
        arrow.closePath();

        // rotate the arrow -90 around its center
        arrowRotate = AffineTransform.getRotateInstance(- Math.PI/2, 20, -20);

        shadowScale = AffineTransform.getScaleInstance(1.0, 0.4);
        shadowShear = AffineTransform.getShearInstance(-1.25, 0.0);
        rotatedArrow = arrowRotate.createTransformedShape(arrow);
        scaledArrow = shadowScale.createTransformedShape(rotatedArrow);
        skewedArrow = shadowShear.createTransformedShape(scaledArrow);

        // This is the code that no longer works
        fontTransform = AffineTransform.getScaleInstance(1.0, -1.0);
           fontTransform.shear(-1.0, 0.0);

        // if you try to just shear the font, it works, if you just scaled
        // it above it works as well.
        // fontTransform = AffineTransform.getShearInstance(-1.0, 0.0);

        reflectionFont = textFont.deriveFont(fontTransform);

        shadowScale.shear(-1.25, 0.0);
        reflectionFont2 = textFont.deriveFont(shadowScale);
            }

            public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D)g;


        // draw Java2D with shadow in back
        g2d.translate(100, 80);
        g2d.setFont(reflectionFont2);
        g2d.setPaint(Color.gray);
        g2d.drawString("Aliased", 0, 0);
        g2d.setPaint(Color.blue);
        g2d.setFont(textFont);
        g2d.drawString("Aliased", 0, 0);

        // draw Java2D with shadow in back
        g2d.translate(300, 0);
        g2d.setRenderingHints(hints1);
        g2d.setPaint(Color.gray);
        g2d.setFont(reflectionFont2);
        g2d.drawString("Anti-Aliased", 0, 0);
        g2d.setPaint(Color.blue);
        g2d.setFont(textFont);
        g2d.drawString("Anti-Aliased", 0, 0);

        // Now draw arrow with shadow
           g2d.translate(-260, 80);
        g2d.setColor(Color.gray);
        g2d.fill(skewedArrow);
        g2d.setColor(Color.blue);
        g2d.fill(rotatedArrow);

        // arrow with shadow and anti-aliasing
        g2d.setRenderingHints(hints1);
        g2d.translate(350, 0);
        g2d.setColor(Color.gray);
        g2d.fill(skewedArrow);
        g2d.setColor(Color.blue);
        g2d.fill(rotatedArrow);
        g2d.setRenderingHints(hints2);
        g2d.translate(-400, 0);

        // Now draw Java2D with shadow in front
        g2d.translate(-80, 60);
        g2d.setFont(textFont);
        g2d.drawString("Java 2D 1 2 3 4 5", 0, 0);
        g2d.setPaint(Color.gray);
        // note the use of using the transformed font like any other
        // font. Its transformation placed its 0,0 location at the top
        // left of its bounds
        g2d.setFont(reflectionFont);
        g2d.drawString("Java 2D 1 2 3 4 5", 0, 0);

        // Now draw Java2D with shadow in front and anti-aliasing
        g2d.translate(350, 0);
        g2d.setColor(Color.blue);
        g2d.setRenderingHints(hints1);
        g2d.setFont(textFont);
        g2d.drawString("Java 2D 1 2 3 4 5", 0, 0);
        g2d.setPaint(Color.gray);
        g2d.setFont(reflectionFont);
        g2d.drawString("Java 2D 1 2 3 4 5", 0, 0);
        g2d.setRenderingHints(hints2);
        g2d.translate(-200, 0);

            }

            public static void main(String argv[]) {
        JFrame j = new JFrame("Affine1.java");
        j.setContentPane(new Affine1());
        j.setSize(500, 400);
        j.setVisible(true);
        j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            }
        }

        ---------- END SOURCE ----------

        CUSTOMER SUBMITTED WORKAROUND :
        None known

        Release Regression From : mustang
        The above release value was the last known release where this
        bug was not reproducible. Since then there has been a regression.

        Attachments

          Issue Links

            Activity

              People

                igor Igor Nekrestyanov (Inactive)
                tyao Ting-Yun Ingrid Yao (Inactive)
                Votes:
                0 Vote for this issue
                Watchers:
                0 Start watching this issue

                Dates

                  Created:
                  Updated:
                  Resolved:
                  Imported:
                  Indexed: