- 
                Notifications
    You must be signed in to change notification settings 
- Fork 185
Description
Describe the bug
Mainly small fonts are looking really bad compared with SWT fonts.
Why do I use AWT fonts? SWT has a limit with antialiasing when drawing into an image, see here mytourbook/mytourbook#1376 (comment)
With autoScale=100 (for none 4k displays) the AWT font rendering is as good as SWT but autoScale > 100 has this issue.
Is there any AWT/SWT parameter to disable AWT font/image scaling when swt.autoScale > 100 ?
To Reproduce
package test4k;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.PaletteData;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
public class SWTvsAWT_FontsAndImages {
   private static int                  AUTO_SCALE;
   private static int                  IMAGE_WIDTH;
   private static int                  IMAGE_HEIGHT;
   private static final String         FONT_NAME            = "Segoe UI";
   private static int[]                FONT_SIZE;
   private static final int            MARGIN               = 2;
   private static final int            SHELL_X              = 1500;
   private static final int            SHELL_Y              = 100;
   private static final int            FOREGROUND_COLOR_SWT = SWT.COLOR_BLACK;
   private static final int            BACKGROUND_COLOR_SWT = SWT.COLOR_WHITE;
   private static final java.awt.Color FOREGROUND_COLOR_AWT = java.awt.Color.black;
   private static final java.awt.Color BACKGROUND_COLOR_AWT = java.awt.Color.white;
   private static Display              _swtDisplay;
   private static Font[]               _swtFont;
   private static int[]                _swtFontHeight;
   static {
      AUTO_SCALE = 200;
      AUTO_SCALE = 100;
      AUTO_SCALE = 150;
      FONT_SIZE = new int[] {
            10,
            12,
            16,
            20,
            24,
//            28,
            36
      };
      System.setProperty("swt.autoScale", Integer.toString(AUTO_SCALE));
      _swtDisplay = new Display();
      int numFonts = FONT_SIZE.length;
      int allFontHeights = 0;
      _swtFont = new Font[numFonts];
      _swtFontHeight = new int[numFonts];
      for (int fontIndex = 0; fontIndex < numFonts; fontIndex++) {
         Font swtFont = new Font(_swtDisplay, FONT_NAME, FONT_SIZE[fontIndex], SWT.NORMAL);
         FontData swtFontData = swtFont.getFontData()[0];
         int fontHeight = swtFontData.getHeight();
         _swtFont[fontIndex] = swtFont;
         _swtFontHeight[fontIndex] = fontHeight;
         allFontHeights += fontHeight;
      }
      IMAGE_WIDTH = 1500;
      IMAGE_HEIGHT = (int) (allFontHeights * 1.8);
   }
   private static String getTestText(int fontIndex) {
      return "  autoScale=%d  FONT SIZE=%d".formatted(AUTO_SCALE, FONT_SIZE[fontIndex]);
   }
   private static Image convertAWTtoSWT(final BufferedImage awtImage) {
      final int imageWidth = awtImage.getWidth();
      final int imageHeight = awtImage.getHeight();
      final ImageData swtImageData = new ImageData(imageWidth, imageHeight, 24, new PaletteData(0xFF0000, 0xFF00, 0xFF));
      final int scansize = (((imageWidth * 3) + 3) * 4) / 4;
      final WritableRaster alphaRaster = awtImage.getAlphaRaster();
      final byte[] alphaBytes = new byte[imageWidth];
      for (int y = 0; y < imageHeight; y++) {
         final int[] buff = awtImage.getRGB(0, y, imageWidth, 1, null, 0, scansize);
         swtImageData.setPixels(0, y, imageWidth, buff, 0);
         if (alphaRaster != null) {
            final int[] alpha = alphaRaster.getPixels(0, y, imageWidth, 1, (int[]) null);
            for (int i = 0; i < imageWidth; i++) {
               alphaBytes[i] = (byte) alpha[i];
            }
            swtImageData.setAlphas(0, y, imageWidth, alphaBytes, 0);
         }
      }
      return new Image(_swtDisplay, swtImageData);
   }
   private static BufferedImage createAWTImage() {
      final BufferedImage awtImage = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT, BufferedImage.TYPE_4BYTE_ABGR);
      final Graphics2D g2d = awtImage.createGraphics();
      try {
         g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
         g2d.setBackground(BACKGROUND_COLOR_AWT);
         g2d.clearRect(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
         int devY = 0;
         for (int fontIndex = 0; fontIndex < FONT_SIZE.length; fontIndex++) {
            java.awt.Font font = new java.awt.Font(FONT_NAME, java.awt.Font.PLAIN, FONT_SIZE[fontIndex]);
            g2d.setFont(font);
            final FontMetrics fontMetrics = g2d.getFontMetrics();
            final int textHeight = fontMetrics.getHeight();
            devY += textHeight;
            g2d.setColor(FOREGROUND_COLOR_AWT);
            g2d.drawString(" AWT" + getTestText(fontIndex), MARGIN, devY);
         }
      } finally {
         g2d.dispose();
      }
      return awtImage;
   }
   private static Image createSWTImage() {
      final Image swtImage = new Image(_swtDisplay, IMAGE_WIDTH, IMAGE_HEIGHT);
      final GC gc = new GC(swtImage);
      {
         gc.setAntialias(SWT.ON);
         gc.setBackground(_swtDisplay.getSystemColor(BACKGROUND_COLOR_SWT));
         gc.fillRectangle(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
         int devY = 0;
         for (int fontIndex = 0; fontIndex < FONT_SIZE.length; fontIndex++) {
            gc.setFont(_swtFont[fontIndex]);
            gc.setForeground(_swtDisplay.getSystemColor(FOREGROUND_COLOR_SWT));
            gc.drawString(" SWT" + getTestText(fontIndex), MARGIN, devY, true);
            devY += _swtFontHeight[fontIndex] + 10;
         }
      }
      gc.dispose();
      return swtImage;
   }
   public static void main(final String[] args) {
      final Image swtImage = createSWTImage();
      final BufferedImage awtImage = createAWTImage();
      final Image swtImageFromAwt = convertAWTtoSWT(awtImage);
      final Shell shell = new Shell(_swtDisplay);
      shell.setText("SWT vs AWT scaling");
      shell.setLocation(SHELL_X, SHELL_Y);
      shell.setSize(IMAGE_WIDTH + 50, IMAGE_HEIGHT * 2 + 30);
      shell.addListener(SWT.Paint, event -> {
         int devY = MARGIN;
         GC gc = event.gc;
         gc.drawImage(swtImage, MARGIN, devY);
         devY += IMAGE_HEIGHT + MARGIN;
         gc.drawImage(swtImageFromAwt, MARGIN, devY);
      });
      shell.open();
      while (!shell.isDisposed()) {
         if (!_swtDisplay.readAndDispatch()) {
            _swtDisplay.sleep();
         }
      }
      swtImage.dispose();
      swtImageFromAwt.dispose();
      for (Font font : _swtFont) {
         font.dispose();
      }
      _swtDisplay.dispose();
   }
}
Expected behavior
AWT within SWT should scale fonts with the same quality as SWT
Screenshots
This screenshot should be viewed without github scaling !
 
Environment:
- Select the platform(s) on which the behavior is seen:
- 
- All OS
 
- 
- [x ] Windows
 
- 
- [?] Linux, not tested
 
- 
- [?] macOS, not tested
 
- 
Additional OS info (e.g. OS version, Linux Desktop, etc) 
 Windows 10
- 
JRE/JDK version 
 java.vendor.version=Temurin-21.0.4+7
Version since
4.23 and older
Workaround (or) Additional context
Have not yet found