Как я могу унаследовать настройку сглаживания системы для рисования текста на изображениях вне экрана, как это делает свинг? - PullRequest
11 голосов
/ 16 декабря 2009

Когда я запускаю свои приложения Swing GUI под Java 6, они автоматически используют мои настроенные субпиксельные настройки сглаживания для всех шрифтов. Результат значительно улучшен по сравнению со стандартными параметрами AA.

Но когда я рисую изображение, я не могу найти способ инициализировать графический контекст для использования конфигурации АА системы. Попытка поиграться с различными советами Java по AA - заблудшая причина, потому что ни один подпиксельный метод не будет работать для всех пользователей.

Есть ли способ унаследовать настройки системного АА для данного графического контекста вместо необходимости выбирать один и явно устанавливать подсказку? На данный момент я должен использовать GASP AA, чтобы избежать ужасных результатов, которые дает стандартный AA с маленькими шрифтами. Я пытался ничего не устанавливать для текста AA и вообще не устанавливать никаких подсказок AA.


Обновление 2010-01-05

Думаю, я это придавил; субпиксельные подсказки AA, по-видимому, учитываются только при рисовании непосредственно в графическом контексте AWT; когда я рисую изображение с двойным буфером, оно просто выполняет стандартную АА; но когда я обхожу изображение с двойным буфером, субпиксель AA завершается.

В противном случае ответ The_Fire будет работать в JVM, у которых есть Swing (но не в J2ME JVM); Обратите внимание, что ответ The_Fire не работает с использованием компонента AWT (использование нового Label () вместо нового сбоя JLabel ()), возможно, потому, что FontRenderContext не может быть извлечен, пока компонент не будет реализован на дисплее.


Мой текущий код для получения графического контекста для моего целевого изображения в настоящее время выглядит следующим образом:

try {
    if((dbImage=dctRoot.createImage(wid,hgt,1))!=null) {            // if createImage returns null or throws an exception the component is not yet displayable
        dbGraphics=(Graphics2D)dbImage.getGraphics();
        if(dctRoot.properties.getBoolean("Antialias",true)) {
            try {
                // set AA on overall
                dbGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING     ,RenderingHints.VALUE_ANTIALIAS_ON);
                // set text AA to platform/impl default
                dbGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);
                // try to override platform/impl AA with font-specified AA (Java 6+)
                try { dbGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.class.getField("VALUE_TEXT_ANTIALIAS_GASP").get(null)); } catch(Throwable thr) {;} // yes, ignore exception
                }
            catch(Throwable thr) {
                dctRoot.log.println("Antialiasing not supported on this JVM ("+thr+").");
                dctRoot.setProperty("Antialias","False");           // turn off AA for subsequent painting
                }
            }
        }
    }
catch(Throwable thr) {
    dbImage=null;
    dbGraphics=null;
    }

Код для создания изображения использует базовый компонент AWT, который формирует фон, на котором я рисую всю картину - это Panel, потому что мне нужно иметь возможность делать setFocusCycleRoot, чтобы он хорошо работал с другими AWT компоненты. Код создания изображения следующий:

public DctImage createImage(int wid, int hgt, float accpty) {
    GraphicsConfiguration               cfg=awtComponent.getGraphicsConfiguration();
    Image                               img=null;

    if(transparentImages) {
        //y { img=new BufferedImage(wid,hgt,BufferedImage.TYPE_INT_ARGB); }     // NB: J2ME CDC/PP 1.1 does not have the BufferedImage constructors (one day I may discover a way to create a BufferedImage via another API!!)
        try { img=cfg.createCompatibleImage(wid,hgt,Transparency.TRANSLUCENT); }// NB: J2ME CDC/PP 1.1 does not have this API, but prefer to use GraphicsConfiguration over new BufferImage(...)
        catch(NoClassDefFoundError   thr) { transparentImages=false; createImage(wid,hgt,accpty); } // try again with transparency disabled
        catch(NoSuchMethodError      thr) { transparentImages=false; createImage(wid,hgt,accpty); } // try again with transparency disabled
        catch(NoSuchFieldError       thr) { transparentImages=false; createImage(wid,hgt,accpty); } // try again with transparency disabled
        }
    else {
        img=cfg.createCompatibleImage(wid,hgt);
        }

    if(accpty>0 && SET_ACCELERATION_PRIORITY!=null) {
        try { SET_ACCELERATION_PRIORITY.invoke(img,new Object[]{new Float(accpty)}); } catch(Throwable thr) {;}
        }

    return (img==null ? null : new DctImage(img));
    }

Ответы [ 4 ]

7 голосов
/ 09 января 2010

Я обнаружил, что здесь происходит несколько факторов.

Во-первых, изображение должно быть создано из базового компонента AWT, и оно должно быть создано без прозрачности:

cfg.createCompatibleImage(wid,hgt);

вместо

cfg.createCompatibleImage(wid,hgt,Transparency.TRANSLUCENT);

Во-вторых, по какой-то необъяснимой причине первичная настройка АА, KEY_ANTIALIASING, должна быть отключена для использования субпикселя ЖК-дисплея АА.

Наконец, и самое главное, подсказки рендеринга шрифтов рабочего стола легко получить с помощью:

java.awt.Toolkit.getDesktopProperty("awt.font.desktophints")

Обновление 2010-01-05

Повторное тестирование в Java 6.26, похоже, что проблема с необходимостью отключения общего AA для рендеринга текста AA, наконец, решена (путь к Oracle ... после того, как Sun прошло всего лишь несколько лет десятилетие слишком поздно).

5 голосов
/ 22 декабря 2009

Используя Swing, я могу получить правильную подсказку сглаживания текста, например:

JLabel label = new JLabel();
FontMetrics fm  = label.getFontMetrics( label.getFont() );
Object aaHintValue = fm.getFontRenderContext().getAntiAliasingHint();

В моей системе это возвращает RenderingHits.VALUE_TEXT_ANTIALIAS_LCD_HRGB.

2 голосов
/ 28 марта 2012

java.awt.Toolkit.getDesktopProperty ("awt.font.desktophints") в Linux выглядит нулевым, по крайней мере, без каких-либо специальных параметров командной строки vm, возможно потому, что он не может определить, какие значения по умолчанию для платформы .. добавление, например, "-Dawt.useSystemAAFontSettings = lcd", похоже, излечивает его и включает субпиксельный рендеринг, если вы установите подсказки для своего экземпляра Graphics2D.

1 голос
/ 23 декабря 2009

Подождите, вы запускаете этот код на Windows JVM? Я думал, что ClearType - это технология Microsoft, которую Swing наследует через некоторый нативный код (т. Е. Недоступный на Linux или других платформах, отличных от Microsoft).

Однажды я написал сервлет, который генерировал JPG с сглаженными шрифтами, работающими в Debian, и это был код, который я использовал

Font font = new Font("Komix", Font.PLAIN, 8);
Graphics2D g2;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
FontRenderContext  frc = g2.getFontRenderContext();
g2.setFont(font);
g2.setPaint(Color.black);
g2.drawString(sMessage, xOffset, yOffset);

Я не могу вспомнить, опирается ли какой-либо код на Swing (я импортировал javax.swing, а длина сервлета составляет около 300 строк, так что, возможно, я подумал, что он мне нужен для чего-то другого), быстрая проверка в Google Похоже, это прямо в пространстве AWT. Надеюсь, это поможет.

...