2010-12-22 2 views
10

Ich habe festgestellt, dass beim Rendern von undurchsichtigem Text in Java (neueste Version 6u23) Sub-Pixel AA nur gut verwendet, Rendering transluzenten Text nicht.Kann Java transparenten Text mit Subpixel AA rendern?

Sub-Pixel-AA:

alt textalt text

Der gleiche Text, für die nur die Farbe von 0xFFFFFFFF zu 0xBFFFFFFF geändert wurde:

alt textalt text

Wie Sie sehen können, Der transluzente Text ist klar Standard-AA und anstatt eines sauberen, durchscheinenden Renderings, hat er dieses schreckliche "spidery" Aussehen der 90er Jahre.

Liegt das an einer technischen Einschränkung für Subpixel AA im Allgemeinen oder an einem Bug in Java, oder nur weil Java nicht einmal nach transparentem Text sucht, oder habe ich etwas verpasst?


Graphics Initialisierung

dbGraphics=(Graphics2D)dbImage.getGraphics(); 
if(dctRoot.properties.getBoolean("Antialias",true)) { 
    try { 
     Map hnts=(Map)(dctRoot.awtComponent.getToolkit().getDesktopProperty("awt.font.desktophints")); 

     // SET AA ON OVERALL (NOTE: GENERAL AA MUST BE OFF FOR SUBPIXEL AA TO BE HONORED - TEXT WIDGETS MUST DO THIS THEMSELVES) 
     dbGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); 

     if(hnts!=null) { 
      // SET FONT RENDERING HINTS FROM DESKTOP 
      dbGraphics.addRenderingHints(hnts); 
      } 
     else { 
      try { 
       // SET TEXT AA TO FONT-SPECIFIED GASP AA (JAVA 6+) 
       dbGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.class.getField("VALUE_TEXT_ANTIALIAS_GASP").get(null)); 
       } 
      catch(Throwable thr3) { 
       // SET TEXT AA TO DEFAULT 
       dbGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON); 
       } 
      } 
     } 
    catch(Throwable thr) { 
     dctRoot.log.println("Antialiasing not supported on this JVM ("+thr+")."); 
     dctRoot.setProperty("Antialias","False");   // turn off AA for subsequent painting 
     } 
    } 
else { 
    try { 
     dbGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF); 
     dbGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); 
     } 
    catch(Throwable thr) {;}        // ignore exception 
    } 

Text Rendering

Object oaa=disableGeneralAA(gc); 
... 
gc.drawString(tl,xx,(ty+(xa*met.getHeight()))); 
restoreGeneralAA(gc,oaa); 

... 


static private volatile boolean   hasRenderingHints=true; 

// ***************************************************************************** 
// STATIC INIT & MAIN 
// ***************************************************************************** 

// ***************************************************************************** 
// STATIC METHODS 
// ***************************************************************************** 

/** 
* Disable the general anti-aliasing rendering hint, returning whether the old value was RenderingHints.VALUE_ANTIALIAS_ON. 
* <p> 
* This method is needed for text rendering due to a bug in AWT; as of Java 6_20 when general AA is on text is not rendered using subpixel 
* AA, so general AA has to be turned off before rendering text and turned back on when done. This method abstracts that work and deals 
* with the possibility that the JVM does not support rendering hints, such as is the case with JME JVMs. 
*/ 
static public Object disableGeneralAA(Graphics2D gc) { 
    Object        old=null; 

    if(hasRenderingHints) { 
     try { 
      old=gc.getRenderingHint(RenderingHints.KEY_ANTIALIASING); 
      gc.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF); 
      } 
     catch(NoClassDefFoundError thr) { hasRenderingHints=false; } 
     catch(NoSuchFieldError  thr) { hasRenderingHints=false; } 
     catch(NoSuchMethodError thr) { hasRenderingHints=false; } 
     } 
    return old; 
    } 

/** 
* Disable the general anti-aliasing rendering hint, returning whether the old value was RenderingHints.VALUE_ANTIALIAS_ON. 
* <p> 
* This method is needed for text rendering due to a bug in AWT; as of Java 6_20 when general AA is on text is not rendered using subpixel 
* AA, so general AA has to be turned off before rendering text and turned back on when done. This method abstracts that work and deals 
* with the possibility that the JVM does not support rendering hints, such as is the case with JME JVMs. 
*/ 
static public void restoreGeneralAA(Graphics2D gc, Object val) { 
    Object        old=null; 

    if(hasRenderingHints && val!=null) { 
     try { gc.setRenderingHint(RenderingHints.KEY_ANTIALIASING,val); } 
     catch(NoClassDefFoundError thr) { hasRenderingHints=false; } 
     catch(NoSuchFieldError  thr) { hasRenderingHints=false; } 
     catch(NoSuchMethodError thr) { hasRenderingHints=false; } 
     } 
    } 
+0

Haben Sie versucht, den Antialias-Text in ein 'BufferedImage' zu ​​übertragen und dann mit einem' AlphaComposite' das Bild transparent auf den Bildschirm zu zeichnen? (Es wird leider langsamer.) – finnw

+0

@finnw: Alle Bilder werden auf einem Offscreen BufferedImage gemacht, und dieses Bild wird in den zugrundeliegenden Bildschirmgrafik-Kontext auf jedem 'paint (Graphics agc)' mit einem einfachen 'gc.drawImage' kopiert . Ich erwarte, dass das Bild im Offscreen-Puffer das endgültige Bild darstellt. Ich mache viel durchsichtiges Malen, und das einzige Problem ist, dass Text-Rendering Standard-AA zu sein scheint, wenn die Textfarbe durchscheinend ist. –

+0

Sieht so aus, als ob dies eine Zeit lang ein Problem gewesen wäre http://forums.java.net/node/676951 – z5h

Antwort

0

ich seine denken, weil Ihr KEUCHEN verwendet, die die Punkte aus dem Schriftstil nimmt. haben Sie versucht, VALUE_TEXT_ANTIALIAS_DEFAULT und VALUE_ALPHA_INTERPOLATION_DEFAULT zu verwenden? einen Versuch ist es wert.

http://download.oracle.com/javase/6/docs/api/java/awt/RenderingHints.html

+0

Nein, ich verwende Sub-Pixel AA; GASP ist nur ein Fallback für den Fall, dass die Desktop-Rendering-Hinweise nicht zurückgegeben werden. Dies wird durch die Screenshots demonstriert - der * einzige * Unterschied zwischen den beiden ist die Farbe, die zum Rendern verwendet wird. –

0

Was Jav eine Version benutzt du? Du sagst es nicht. Aber anscheinend hat dies als entweder Java 6 Update behoben 12 (J6u12) oder JDK7 b43

Siehe hier: http://bugs.sun.com/view_bug.do?bug_id=6749060

Wenn Ihr Test erneut mit Java = oder höher als J6u12 und nach wie vor den Bug sehen, da Ist ein RFE, wo Sie bei Suns Fehlerdatenbank kommentieren können.

So wie die Dinge in der Java-Plattform festgelegt zu bekommen, ist entweder:

  1. Abstimmung über den Fehlerbericht an Sun's BugParade, seine Priorität zu erhöhen, und warten, bis die Sonne/Oracle Programmierer erhalten dazu oder
  2. Nun, da Java Open Source ist, reparieren Sie es selbst. (Tritt der Mailingliste bei ho bei.io/jkp5 :-)

Der Bugparade Bericht Sie in wählen wollen oder einen Kommentar hier ist (falls Sie testen mit j6u12 einem Es ist noch vorhanden) url: ho.io/jkp2

Wenn Sie eine bekannte Behelfslösung implementieren, so der Text auch schön aussieht um work-in älterem JREs a vorgesehen ist, hier

url: ho.io/jkpy

„, wie die Lösung sucht, die i‘ m, um die Transluzenz zu emulieren, indem die erforderliche Vordergrundfarbe mit der Hintergrundfarbe der Komponenten gemischt wird Es ist immer noch der richtige Weg, um sicherzustellen, dass der native Rasterizer verwendet wird. "

Viel Glück!

+0

Es ist sicherlich nicht ab 6.23 behoben; Ich betreibe die neueste JVM und JDK. Ich stelle fest, dass es sich dabei um das Ziel handelt, das nicht opak ist, und ich benutze eine durchscheinende Quelle, aber ich vermute, dass das Problem darin besteht, dass überhaupt ein Alpha-Blending auftritt. –

+0

Und die Transluzenz selbst kommt nicht in Frage, da der Hintergrund, über den der Test gerendert wird, variiert - es ist oft ein Bild, Logo oder Farbverlauf - es gibt keine einzige Farbe, die für alle Pixel funktioniert. –