2016-04-14 5 views
21

Sembra che segnare su coordinate sub-pixel venne ripartito in Java 8.Java 8 grafici inconveniente quando segnando sub-pixel coordinate su Linux

Ho tre serie di casi, indicati su schermate (colonne rappresentano casi, righe rappresentare diverse larghezze ictus):

7u51 Java (scala 400%)
Screenshot on Java 7u51 (400% scale)
Java 8u60 (scala 400%)
Screenshot on Java 8u60 (400% scale)

  1. Riempi e tratti sulle stesse coordinate. Funziona come previsto, l'area segnata è più grande dell'area di riempimento.
  2. Il tratto viene ridotto (in base alla larghezza del tratto) e centrato (per metà della larghezza) all'interno dei limiti dell'area di riempimento. Questa parte è interrotta in Java 8 per 1px stroke, in cui la pittura si verifica su una coordinata sub-pixel (prima riga); Il colpo 3px non ha questo problema (terza riga). Sembra che 0.5 sia arrotondato per il colpo di 1px.
  3. Il rettangolo di riempimento è ristretto centrato nello stesso modo del caso 2. Ho bisogno di questo sulla grafica, che supporta il disegno sub-pixel, per rendere il riempimento non sovrapposto quando le celle si sovrappongono. Qui puoi vedere che l'operazione di riempimento va da 0,5 a 0, quindi è solo un problema di carezze.

Il codice è qui sotto:

import static java.awt.BasicStroke.*; 

import java.awt.*; 
import java.awt.geom.*; 

import javax.swing.*; 

public class TestCase 
{ 
    public static void main(String[] args) 
    { 
     JFrame frame = new JFrame("Test case"); 
     frame.setSize(115, 115); 
     frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 

     frame.getContentPane().add(new TestPanel()); 

     frame.setVisible(true); 
    } 

    private static class TestPanel extends JPanel 
    { 
     TestPanel() 
     { 
      setOpaque(true); 
     } 

     @Override 
     protected void paintComponent(Graphics g) 
     { 
      Graphics2D g2 = (Graphics2D) g; 
      g2.setColor(Color.white); 
      g2.fill(getBounds()); 

      Rectangle2D rect = new Rectangle2D.Double(); 
      Color background = new Color(0, 255, 255); 
      Color border = new Color(255, 0, 0, 128); 
      Stroke STROKE_1PX = new BasicStroke(1, CAP_SQUARE, JOIN_MITER); 
      Stroke STROKE_2PX = new BasicStroke(2, CAP_SQUARE, JOIN_MITER); 
      Stroke STROKE_3PX = new BasicStroke(3, CAP_SQUARE, JOIN_MITER); 
      g2.translate(10, 10); 

      /** 
      * Filling and stroking by original coordinates 
      */ 
      rect.setRect(0, 0, 25, 25); 
      g2.setColor(background); 
      g2.fill(rect); 
      g2.setColor(border); 
      g2.setStroke(STROKE_1PX); 
      g2.draw(rect); 
      g2.translate(0, 35); 
      g2.setColor(background); 
      g2.fill(rect); 
      g2.setColor(border); 
      g2.setStroke(STROKE_2PX); 
      g2.draw(rect); 
      g2.translate(0, 35); 
      g2.setColor(background); 
      g2.fill(rect); 
      g2.setColor(border); 
      g2.setStroke(STROKE_3PX); 
      g2.draw(rect); 

      /** 
      * Stroking is shrunk to be inside the filling rect 
      */ 
      g2.translate(35, -70); 
      rect.setRect(0, 0, 25, 25); 
      g2.setColor(background); 
      g2.fill(rect); 
      rect.setRect(0.5, 0.5, 24, 24); 
      g2.setColor(border); 
      g2.setStroke(STROKE_1PX); 
      g2.draw(rect); 
      g2.translate(0, 35); 
      rect.setRect(0, 0, 25, 25); 
      g2.setColor(background); 
      g2.fill(rect); 
      rect.setRect(1, 1, 23, 23); 
      g2.setColor(border); 
      g2.setStroke(STROKE_2PX); 
      g2.draw(rect); 
      g2.translate(0, 35); 
      rect.setRect(0, 0, 25, 25); 
      g2.setColor(background); 
      g2.fill(rect); 
      rect.setRect(1.5, 1.5, 22, 22); 
      g2.setColor(border); 
      g2.setStroke(STROKE_3PX); 
      g2.draw(rect); 

      /** 
      * Filling rect is additionally shrunk and centered 
      */ 
      g2.translate(35, -70); 
      rect.setRect(0.5, 0.5, 24, 24); 
      g2.setColor(background); 
      g2.fill(rect); 
      g2.setColor(border); 
      g2.setStroke(STROKE_1PX); 
      g2.draw(rect); 
      g2.translate(0, 35); 
      rect.setRect(1, 1, 23, 23); 
      g2.setColor(background); 
      g2.fill(rect); 
      g2.setColor(border); 
      g2.setStroke(STROKE_2PX); 
      g2.draw(rect); 
      g2.translate(0, 35); 
      rect.setRect(1.5, 1.5, 22, 22); 
      g2.setColor(background); 
      g2.fill(rect); 
      g2.setColor(border); 
      g2.setStroke(STROKE_3PX); 
      g2.draw(rect); 
     } 
    } 
} 

Come ho provato, Java 7 non ha questo problema (provato su 7u51), Windows (8u77) e Mac (8u60) troppo. Provato su Ubuntu (8u60 e 8u77) e Linux Mint (8u60) su macchine diverse e il bug era qui.

Qualcuno ha affrontato questo problema? C'è qualche soluzione generale?

Non riesco a gestire il caso 1px nei punti in cui viene utilizzato il tratto. E 'perché c'è un sacco di posti e sto lavorando con diversi Graphics2D implementazioni e sembra, che da quello che ho usato la questione riproduce solo su SunGraphics2D. Ciò significa che ho bisogno di usare instanceOf in questi luoghi per non rompere la logica comune.

+1

StackOverflow non è un meccanismo di segnalazione errori.Per segnalare un problema con Java visita bugreport.java.com e includi la tua classe demo e qualsiasi altra cosa di cui hanno bisogno per replicare il problema. – dimo414

+0

Sto votando per chiudere questa domanda come off-topic perché è una segnalazione di bug. – dimo414

+4

Ho inviato un bug a bugtracker, ma non spero di vedere presto la correzione. Perché è un bug nella grafica. Ho inviato un altro bug quasi mezzo anno fa e ancora non ho ricevuto alcuna notifica sui suoi progressi. Avrei bisogno di una soluzione alternativa per convivere con questo problema finché non viene risolto. –

risposta

1

Da bug report discussione:

Si tratta di un bug di XRender -Dsun.java2d.xrender = falsi guarisce.

Non ho verificato personalmente questa soluzione poiché non ho ricevuto alcuna notifica dal sistema di segnalazione bug oltre che è stata esaminata. E dato che era un problema solo per Linux, si è deciso di aspettare le correzioni ufficiali perché non c'erano molti utenti Linux tra i nostri clienti.

0

Suggerirei di estendere Graphics2D e aggiungere misure correttive lì sui punti dove necessario.

In questo modo è possibile mantenere il flusso principale coerente, e aggiungere tutti gli altri errori "logica" possono essere gestite dove hanno bisogno di essere trattati.

Ciò consente di risparmiare l'overhead di modificare i file N e annullando le modifiche se viene risolto, e mantenere la logica dove dovrebbe essere.

+0

In realtà sto usando diversi oggetti grafici (per renderizzare su dispositivi diversi), che sono impostati implicitamente. E come ricordo che SunGraphics2D, che viene utilizzato internamente, non può essere esteso. Grazie a te, ho controllato il bug report e la soluzione alternativa dallo staff Oracle. –