Как я могу унаследовать настройку сглаживания системы для рисования текста на изображениях вне экрана, как это делает качели?

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

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

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


Обновление от 05 января 2010 г.

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

В противном случае ответ The_Fire будет работать в JVM, в которых доступен Swing (но не J2ME JVM); Обратите внимание, что ответ The_Fire не работает с использованием компонента AWT (не удается использовать new Label () вместо new 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));
    }

person Lawrence Dol    schedule 15.12.2009    source источник
comment
Не имеет отношения к экранному или внеэкранному режиму (так что это комментарий, а не ответ), но вы знаете, как определенные посторонние символы в строке заставляют Swing переключаться обратно на рендеринг шрифта TextLayout (который не сглаживается ), правильно?   -  person whybird    schedule 16.12.2009


Ответы (4)


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

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

cfg.createCompatibleImage(wid,hgt);

вместо

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

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

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

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

Обновление от 05 января 2010 г.

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

person Lawrence Dol    schedule 09.01.2010

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

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

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

person The_Fire    schedule 22.12.2009
comment
Это интересная мысль. Я не могу использовать Swing - не поддерживается в J2ME / CDC / PP - но я могу получить то же самое из окна AWT. - person Lawrence Dol; 23.12.2009
comment
Мне нужно проверить это на работе ... но поскольку getFontMetrics () является методом компонентов, я полностью ожидаю, что это сработает в моем контексте. Если это так, вы можете ожидать принятия этого решения в январе. - person Lawrence Dol; 24.12.2009
comment
Давать ему +1, потому что это помогает получить правильную подсказку AA; но он не работает для AWT (предположительно, потому что собственный компонент не реализован), и даже применение указанной подсказки ЖК-дисплея не приводит к субпиксельному AA, что мне нужно для решения моей проблемы. - person Lawrence Dol; 06.01.2010
comment
Очевидно, прошло несколько лет, и поэтому Java, которую вы используете, вероятно, отличается от той, которую я использую, но в моей системе (Java 7, Mac OS 10.9) этот код возвращает VALUE_TEXT_ANTIALIAS_ON - что действительно использует Java. , хотя сама ОС использует субпиксельный рендеринг. - person Trejkaz; 11.12.2013
comment
@Trejkaz: Вы пропустили, я подозреваю, часть о том, что он нужен для работы с чистым AWT, а не с использованием Swing. Приведенный выше код работает (и работал), но не без Swing. - person Lawrence Dol; 09.07.2014
comment
@LawrenceDol да? Я просто указал на то, что поведение изменилось. Я ничего не сказал о том, что он работает или не работает. - person Trejkaz; 14.07.2014
comment
@Trejkaz: Хорошо, тогда я неправильно понял суть вашего комментария; Извините. - person Lawrence Dol; 14.07.2014

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

person Jesper Matthiesen    schedule 28.03.2012
comment
Toolkit.getDefaultToolkit (). GetDesktopProperty (awt.font.desktophints); - person Hanynowsky; 09.06.2012

Подождите, вы запускаете этот код на 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. Надеюсь, это поможет.

person Jason Sperske    schedule 23.12.2009
comment
Да, я могу включить AA достаточно легко, но он использует стандартный AA, который выглядит чушью при любом размере шрифта менее 20 pt; использование GASP AA работает лучше, но имеет тенденцию просто отключать AA для меньшего размера шрифта. Лучше всего использовать субпиксельный AA, но вы должны согласовывать аппаратное расположение пикселей (вертикальное или горизонтальное и RGB или BGR). Я хотел бы унаследовать любые настройки AA, которые использует операционная система, поскольку это будет либо правильно, либо, по крайней мере, равно тому, что пользователь видит на своем рабочем столе в целом. Настоящая проблема в том, что стандартный AA выглядит чушью рядом с субпиксельным AA. - person Lawrence Dol; 24.12.2009
comment
Кстати, хотя ClearType является товарным знаком Microsoft, задействованная технология представляет собой субпиксельное сглаживание, которое доступно на всех основных платформах. - person Lawrence Dol; 08.11.2010