opencollab / jlatexmath

A Java API to render LaTeX
Other
514 stars 109 forks source link

Distorted Graphics2D output (letter height) when using JRE11 #54

Closed qwert2003 closed 5 years ago

qwert2003 commented 5 years ago

There is a rendering issue that occurs with JRE11, but not with JRE8 (or 1.7). It happens when doing vector rendering, e.g. using any of the following Graphics2d backends: epsgraphics, freehep, jfreesvg, orsonpdf, jtikz. But none of this backends is affected when using g.drawString() instead of jlatexmath.

png output (ok for both JRE8 and JRE11): out2_JRE11

JRE 11 (distorted): out2_JRE11_eps.pdf

JRE 8 (ok): out2_JRE8_eps.pdf

Unfortunately I was not able to track down the issue.

Example code (showIssue2.zip):

/* Test case */
package ShowIssue;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.io.FileOutputStream;
import java.io.IOException;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import net.sf.epsgraphics.ColorMode;
import net.sf.epsgraphics.EpsGraphics;
import org.scilab.forge.jlatexmath.Box;
import org.scilab.forge.jlatexmath.TeXConstants;
import org.scilab.forge.jlatexmath.TeXFormula;
import org.scilab.forge.jlatexmath.TeXIcon;

/**
 *
 * @author av 2019
 */
public class showIssue2 {
    boolean success = true;

    public showIssue2 () {
        int pxwidth = 80;
        int pxheight = 50;
        // writing to an image works in both JRE8 and JRE11
        writeOutput(pxwidth, pxheight, "out2.png");
        // writing to anything else distorts the height of jlatexmath formula
        // tested: epsgraphics, jfreesvg, orsonpdf, jtikz, freehep
        writeOutputEPS(pxwidth, pxheight, "out2.eps"); 
    }

    private void draw(Graphics2D g) {
        g.setColor(Color.BLACK);
        g.setStroke(new BasicStroke(1f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));

        int fontsize = 12;
        g.setFont(new java.awt.Font("Serif", Font.PLAIN, fontsize));
        g.drawString("x = √25", 10f, 15f);

        double xpix = 10;
        double ypix = 40;
        String latex = "x = \\sqrt{25}";
        TeXFormula formula = new TeXFormula(latex);

        formula.setColor(g.getColor());
        formula.setDEBUG(false);
        //formula.createPNG(TeXConstants.STYLE_TEXT, 200, "out.png", Color.WHITE, Color.BLACK);
        TeXIcon icon = formula.createTeXIcon(TeXConstants.STYLE_TEXT, fontsize, true);

        Graphics2D tempGraphics = (Graphics2D) g.create();
        tempGraphics.translate(xpix, ypix);
        tempGraphics.scale(fontsize, fontsize);

        // draw formula box
        Box box = icon.getBox();
        box.draw(tempGraphics, 0, 0);

        tempGraphics.dispose();
    }

    public static void main(String[] args) {
        showIssue2 c1 = new showIssue2();
    }

    private void writeOutputEPS(int pxwidth, int pxheight, String filename) {
        try {
            FileOutputStream file = new FileOutputStream(filename);
            EpsGraphics eps = new EpsGraphics(filename, file,
                    0, 0, pxwidth, pxheight, ColorMode.COLOR_RGB);

            draw(eps);

            eps.close();
            file.close();
        } catch (IOException ex) {
            System.err.println(ex.getLocalizedMessage());
            success = false;
        }

        if (success) {
            System.out.println("Output written to: " + filename);
        } else {
            System.out.println("Error occurred. Check for error messages.");
        }
    }

    private void writeOutput(int pxwidth, int pxheight, String filename) {
        try {
            FileOutputStream file = new FileOutputStream(filename);
            int imgtype = BufferedImage.TYPE_INT_ARGB; // including transparency (alpha channel)
            BufferedImage bi = new BufferedImage(pxwidth, pxheight, imgtype);
            Graphics2D ig2 = bi.createGraphics();
            ig2.setColor(Color.WHITE);
            ig2.fillRect(0, 0, pxwidth, pxheight);
            draw(ig2);
            ImageIO.write(bi, "png", file);
            file.close();
        } catch (IOException ex) {
            System.err.println(ex.getLocalizedMessage());
            success = false;
        }

        if (success) {
            System.out.println("Output written to: " + filename);
        } else {
            System.out.println("Error occurred. Check for error messages.");
        }
    }

}
murkle commented 5 years ago

I've made a quick test with GeoGebra 5.0.426.0 (which uses JLM v1) and JRE11.0.2.9.3 from https://docs.aws.amazon.com/corretto/latest/corretto-11-ug/downloads-list.html and it seems to work OK exporting to PNG and SVG using FreeHEP

qwert2003 commented 5 years ago

Thanks for your encouraging response. Indeed, with the JRE11 versions "Corretto-11.0.2.9.3", both on Linux (OpenSuse Leap 42.3) and Windows (10), the issue does not happen. The rendering is correct. I am quite happy about that, as the issue apparently broke an important feature (TeX rendering) of my project drawj2d.

The issue still occurs on Linux using the JRE11 (OpenJDK 64-Bit Server VM (build 11.0.2+7-suse-114.20-x8664, mixed mode)) provided by the OpenSuse repo http://download.opensuse.org/repositories/Java:/Factory/openSUSE_Leap_42.3/ .

A question remains. Does jlatexmath rely on any default font metrics or similar?

murkle commented 5 years ago

I can't think of anywhere it relies on defaults.

Given https://www.redhat.com/en/about/press-releases/leadership-openjdk-8-and-openjdk-11-transitions-red-hat I would test on Red Hat and if it works there then it's a bug with OpenSuse

qwert2003 commented 5 years ago

I've reported the issue to a OpenSUSE "java-11-openjdk" package maintainer.

qwert2003 commented 5 years ago

OpenSUSE has fixed its "java-11-openjdk" packages. I do not see the issue any more.

It turns out initially I have reported the issue to the wrong project. Thanks for your helpful comments! So I could report the issue "upstream" and it has got fixed quickly.