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

Printing JavaFX node with complex clip is pixelated.

XMLWordPrintable

    • aarch64
    • os_x

      ADDITIONAL SYSTEM INFORMATION :
      Mac OS Big Sur

      A DESCRIPTION OF THE PROBLEM :
      On macOS Big Sur, running JDK 17 and JavaFX 18, when you have an irregular clipping region, the clipped image ends up badly pixelated when printed.

      The pixelation happens both on actual paper (on my Epson printer), as well as when saved to a PDF (using macOSs innate "Save to PDF" feature).

      If you have a clip region with a Rectangle, there is no pixelation, everything looks smooth and crisp.

      Note, that it must be a Rectangle, a rectangular Polygon has problems as well.

      Seems to me that its rendering the node in to the "PDF resolution", which is 72 DPI (not actual printer resolution), and then masking the region using a bitmap operation rather than actually clipping the content to the irregular border. But it special cases the Rectangle and clips to that.

      I have a post on StackOverflow with some images.

      https://stackoverflow.com/questions/72723418/printing-pixelates-when-clipped



      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the attached program. Click the Print button. Either Save to PDF, or Print to paper and observe the results.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      I was expecting to see the text and lines in the circle region to be in the same resolution as the text and lines in the rectangle region.
      ACTUAL -
      The text and lines within the circle region are at a lower resolution than the text and lines in the rectangular region.

      ---------- BEGIN SOURCE ----------
      package pkg;

      import javafx.application.Application;
      import javafx.print.PrinterJob;
      import javafx.scene.Scene;
      import javafx.scene.control.Button;
      import javafx.scene.layout.BorderPane;
      import javafx.scene.layout.FlowPane;
      import javafx.scene.layout.Pane;
      import javafx.scene.layout.StackPane;
      import javafx.scene.shape.Circle;
      import javafx.scene.shape.Line;
      import javafx.scene.shape.Rectangle;
      import javafx.scene.text.Text;
      import javafx.stage.Stage;

      public class App extends Application {

          Pane printPane;

          @Override
          public void start(Stage stage) {
              var scene = new Scene(getView(), 640, 480);
              stage.setScene(scene);
              stage.show();
          }

          public static void main(String[] args) {
              launch();
          }

          private Pane getView() {
              var flowPane = new FlowPane(getCirclePane(), getRectPane());
              var b = new Button("Print");
              printPane = flowPane;
              b.setOnAction((t) -> {
                  var job = PrinterJob.createPrinterJob();

                  if (job != null && job.showPrintDialog(null)) {
                      if (job.printPage(printPane)) {
                          job.endJob();
                      }
                  }

              });
              var bp = new BorderPane();
              bp.setCenter(flowPane);
              bp.setBottom(b);

              return bp;
          }

          private Pane getCirclePane() {
              var pane = new Pane();
              var circle = new Circle(100, 100, 45);
              pane.setClip(circle);
              var text = new Text(75, 100, "Circle");
              pane.getChildren().add(text);
              for (int i = 0; i < 10; i++) {
                  double ox = i * 25;
                  pane.getChildren().add(new Line(ox, 200, ox + 25, 0));
                  pane.getChildren().add(new Line(ox, 0, ox + 25, 200));
              }

              return pane;
          }

          private Pane getRectPane() {
              var pane = new Pane();
              var rect = new Rectangle(50, 50, 200, 125);
              pane.setClip(rect);
              var text = new Text(125, 100, "Rectangle");
              pane.getChildren().add(text);
              for (int i = 0; i < 10; i++) {
                  double ox = i * 25;
                  pane.getChildren().add(new Line(ox, 200, ox + 25, 0));
                  pane.getChildren().add(new Line(ox, 0, ox + 25, 200));
              }

              return pane;
          }

      }

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

      FREQUENCY : always


            prr Philip Race
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated: