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

The CSS FontConverter class erroneously converts font sizes to pixels

XMLWordPrintable

    • generic
    • generic

      ADDITIONAL SYSTEM INFORMATION :
      OS: Microsoft Windows 11 Home 10.0.26100 Build 26100
      Device: Surface Pro 7 with a 2736x1824 display
      Java version: OpenJDK Runtime Environment Temurin-24.0.1+9 (build 24.0.1+9)
      JavaFX version: 24.0.1

      A DESCRIPTION OF THE PROBLEM :
      The documentation of javafx.scene.text.Font says its size is in points, not
      pixels. Yet the javafx.css.converter.FontConverter class, as well as its nested
      FontSizeConverter class, converts the font size to pixels before creating a
      Font via one of the Font::font(...) static factory methods.

      Since the size unit of Font is points, the FontConverter class should convert
      the size to points instead of pixels. That way setting the font size via CSS
      with -fx-font: 30pt "System"; and setting the font size via code with
      Font.font("System", 30.0) result in the same font size.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1) Compile and run test code.

      2) Observe the text with its font size set to 30pt via CSS is larger than the
         text with its font size set to 30pt via CODE even though the two sizes are
         ostensibly the same.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Orange text (30pt via CSS) and red text (30pt via CODE) should be the same
      size, with green text (30px via CSS) being smaller.
      ACTUAL -
      Orange text (30pt via CSS) is larger than both red text (30pt via CODE) and
      green text (30px via CSS), with the latter two erroneously being the same size.

      ---------- BEGIN SOURCE ----------
      import javafx.application.Application;
      import javafx.geometry.Insets;
      import javafx.geometry.Pos;
      import javafx.scene.Scene;
      import javafx.scene.layout.HBox;
      import javafx.scene.paint.Color;
      import javafx.scene.text.Font;
      import javafx.scene.text.Text;
      import javafx.stage.Stage;

      public class Main extends Application {

        /*
         * The orange text has its font size set to 30 *points* via CSS. The green
         * text has its font size set to 30 *pixels* via CSS. And the red text has
         * its font size set to 30 *points* via code. This means the orange text
         * and the red text should be the same size while the green text is smaller.
         *
         * What actually occurs is that the orange text is larger than both the green
         * and the red text, where the latter two are the same size.
         */

        @Override
        public void start(Stage primaryStage) {
          // Set font size to 30pt via CSS
          var ptText = new Text("Test");
          ptText.setFill(Color.ORANGE);
          ptText.setStyle("-fx-font: 30pt 'System';");

          // Set font size to 30px via CSS
          var pxText = new Text("Test");
          pxText.setFill(Color.GREEN);
          pxText.setStyle("-fx-font: 30px 'System';");

          // Set font size to 30pt via code
          var codeText = new Text("Test");
          codeText.setFill(Color.RED);
          codeText.setFont(Font.font("System", 30.0));

          var root = new HBox(5.0, ptText, pxText, codeText);
          root.setAlignment(Pos.BASELINE_CENTER);
          root.setPadding(new Insets(10.0));

          primaryStage.setScene(new Scene(root, 300, -1));
          primaryStage.show();

          /*
           * Print the (LOGICAL) text heights only after CSS has been applied. The
           * output is:
           *
           * Text height with font size '30pt' set via ' CSS' = 53.20
           * Text height with font size '30px' set via ' CSS' = 39.90
           * Text height with font size '30pt' set via 'CODE' = 39.90
           *
           * Which suggests points are converted to pixels using a DPI of 96. For
           * instance, 30pt * (96dpi / 72ppi) is approximately 40 pixels, which is
           * what the height for 30pt font size via CODE is. But the same conversion
           * occurs for a font size of 30px via CSS even though the size is already
           * in pixels. And when the font size is set to 30pt via CSS it looks like
           * the conversion is applied *twice*--once by FontConverter and then again
           * by whatever code is responsible for rendering the text.
           */
          printTextHeight("30pt", "CSS", ptText);
          printTextHeight("30px", "CSS", pxText);
          printTextHeight("30pt", "CODE", codeText);
        }

        private void printTextHeight(String size, String source, Text text) {
          var fmt = "Text height with font size '%s' set via '%4s' = %.2f%n";
          System.out.printf(fmt, size, source, text.getLayoutBounds().getHeight());
        }
      }
      ---------- END SOURCE ----------

        1. screenshot.png
          8 kB
          Anupam Dev
        2. Test.java
          3 kB
          Anupam Dev

            arapte Ambarish Rapte
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: