Hi,

another big difference when using the a BufferedImage is to that the
font rendering is catastrophic, hope to offend nobody. I'm not very good
a AWT maybe I made a dumb mistake?

See http://downloads.efxclipse.org/font_j2d_fx.png - the j2d font looks
completely blurred in contrast to the sharp JavaFX Canvas version in the
foreground.

Similar blurring happens when makeing screenshots of a canvas - I've
written a small sample application showing problems I am seeing which
gets me to an image as in this link
http://downloads.efxclipse.org/screen_compare.png.

Could I somehow use the javafx font-rendering push it to a bitmap and
draw it on the buffered image?

Anyways those are all only workarounds for javafx canvas inefficiencies
that e.g. awt does not have.

> package application;
>       
> import java.awt.Graphics2D;
> import java.awt.RenderingHints;
> import java.awt.image.BufferedImage;
> 
> import javafx.application.Application;
> import javafx.embed.swing.SwingFXUtils;
> import javafx.geometry.VPos;
> import javafx.scene.Node;
> import javafx.scene.Scene;
> import javafx.scene.SnapshotParameters;
> import javafx.scene.canvas.Canvas;
> import javafx.scene.control.Label;
> import javafx.scene.image.ImageView;
> import javafx.scene.image.WritableImage;
> import javafx.scene.layout.HBox;
> import javafx.scene.layout.VBox;
> import javafx.scene.paint.Color;
> import javafx.scene.text.Font;
> import javafx.stage.Stage;
> 
> 
> public class Main extends Application {
>       private WritableImage img;
>       
>       @Override
>       public void start(Stage primaryStage) {
>               try {
>                       HBox root = new HBox();
>                       Scene scene = new Scene(root,400,400);
>                       
> scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
>                       
>                       root.getChildren().add(createCanvas());
>                       root.getChildren().add(createBufferedCanvas());
>                       root.getChildren().add(new VBox(new ImageView(img), new 
> Label("Snapshot")));
>                       
>                       primaryStage.setScene(scene);
>                       primaryStage.show();
>               } catch(Exception e) {
>                       e.printStackTrace();
>               }
>       }
>       
>       private Node createBufferedCanvas() {
>               VBox b = new VBox();
>               b.setStyle("-fx-border-style: solid; -fx-border-width: 2px;");
>               Canvas c = new Canvas(150, 150);
>               BufferedImage img = new BufferedImage(150, 150, 
> BufferedImage.TYPE_INT_ARGB);
>               Graphics2D graphics = img.createGraphics();
>               
> graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
>               graphics.setColor(java.awt.Color.BLACK);
>               graphics.setFont(new java.awt.Font(Font.getDefault().getName(), 
> java.awt.Font.PLAIN, 20));
>               graphics.drawString("Hello World!", 0, 20);
>               img.flush();
>               c.getGraphicsContext2D().drawImage(SwingFXUtils.toFXImage(img, 
> null),10,10);
>               
>               b.getChildren().add(c);
>               b.getChildren().add(new Label("Buffered-Canvas"));
>               
>               return b;
>       }
>       
>       private Node createCanvas() {
>               VBox b = new VBox();
>               b.setStyle("-fx-border-style: solid; -fx-border-width: 2px;");
>               Canvas c = new Canvas(150, 150);
>               
> c.getGraphicsContext2D().setFont(Font.font(Font.getDefault().getName(),20));
>               c.getGraphicsContext2D().setTextBaseline(VPos.TOP);
>               c.getGraphicsContext2D().fillText("Hello World", 10, 10);
>               
>               SnapshotParameters parameters = new SnapshotParameters();
>               parameters.setFill(Color.TRANSPARENT);
>               img = c.snapshot(parameters,null);
>               
>               b.getChildren().add(c);
>               b.getChildren().add(new Label("FX-Canvas"));
>               return b;
>       }
>       
>       public static void main(String[] args) {
>               launch(args);
>       }
> }

Tom

On 24.05.14 02:46, Tom Schindl wrote:
> Hi,
> 
> As an experiment I've now written a SWT-GC implementation using a
> BufferedImage & Graphics2D and transfering the pixels over to JavaFX and
> the performance is as it is with native SWT.
> 
> I always thought Canvas works similar to Image and one only draws pixels
> - looks like that is not the case, having a dep in my application
> java.awt is not what I'm aiming at but without acceptable performance in
> conjunction with clipping it looks like i have to go this route :-(
> 
> Tom
> 
> On 23.05.14 23:57, Tom Schindl wrote:
>> In the current usecase it is a rect all time but that's just in this special 
>> use case. 
>>
>> I guess that rect clipping is the most common one so having an optimization 
>> for rects and a slow path for none rects might help.
>>
>> Tom
>>
>> Von meinem iPhone gesendet
>>
>>> Am 23.05.2014 um 23:35 schrieb Jim Graham <james.gra...@oracle.com>:
>>>
>>> Are you clipping to an arbitrary path in all cases or just a rectangle?  
>>> Unfortunately we only offer the arbitrary clip-to-current-path method that 
>>> isn't optimized for basic rectangular clipping and it implements soft 
>>> clipping.
>>>
>>> There is an outstanding tweak that we added faster clipping support for 
>>> WebNode and we need to start using it for Node.setClipNode(non-rectangle) 
>>> and Canvas, but we haven't implemented that yet.  
>>> (https://javafx-jira.kenai.com/browse/RT-30107)  It basically is a direct 
>>> "render this texture through that other texture as a clip" operation 
>>> instead of the current code that runs it through some Blend effect filters. 
>>>  It would definitely improve your run times, but I'm not sure how much.
>>>
>>> Even more savings could be had for rectangular clips if we provided some 
>>> way to communicate them to the GC...
>>>
>>>            ...jim
>>>
>>>> On 5/23/14 11:47 AM, Tom Schindl wrote:
>>>> Hi,
>>>>
>>>> Maybe as some of you might know I've been working since sometime on SWT
>>>> on JavaFX and to implement direct drawing operations we use JavaFX-Canvas.
>>>>
>>>> I've today tried to run a heavy direct drawing grid implementation and
>>>> it performed very bad because it makes heavy use of clipping.
>>>>
>>>> For a grid I've counted ~1500 clipping operations the library works
>>>> something like this:
>>>>
>>>> boolean activeClip;
>>>> Canvas canvas = new Canvas();
>>>>
>>>> public void setClipping(PathIterator pathIterator) {
>>>>   GraphicsContext gc = canvas.getGraphicsContext2D();
>>>>   if(activeClip) {
>>>>     gc.restore();
>>>>     activeClip= false;
>>>>   }
>>>>
>>>>   if( pathIterator == null ) {
>>>>     return;
>>>>   }
>>>>
>>>>   activeClip = true;
>>>>   float coords[] = new float[6];
>>>>   gc.save();
>>>>        gc.beginPath();
>>>>        
>>>>        float x = 0;
>>>>        float y = 0;
>>>>        
>>>>        
>>>>        gc.moveTo(0, 0);
>>>>        
>>>>        while( ! pathIterator.isDone() ) {
>>>>            switch (pathIterator.currentSegment(coords)) {
>>>>            case PathIterator.SEG_CLOSE:
>>>>                gc.lineTo(x, y);
>>>>                break;
>>>>            case PathIterator.SEG_CUBICTO:
>>>>                gc.bezierCurveTo(coords[0], coords[1], coords[2], coords[3],
>>>> coords[4], coords[5]);
>>>>                break;
>>>>            case PathIterator.SEG_LINETO:
>>>>                gc.lineTo(coords[0], coords[1]);
>>>>                break;
>>>>            case PathIterator.SEG_MOVETO:
>>>>                gc.moveTo(coords[0], coords[1]);
>>>>                x = coords[0];
>>>>                y = coords[1];
>>>>                break;
>>>>            case PathIterator.SEG_QUADTO:
>>>>                gc.quadraticCurveTo(coords[0], coords[1], coords[2], 
>>>> coords[3]);
>>>>                break;
>>>>            default:
>>>>                break;
>>>>            }
>>>>            pathIterator.next();
>>>>        }
>>>>        
>>>>        gc.clip();
>>>>        gc.closePath();
>>>> }
>>>>
>>>> Am I doing something ultimately wrong, totally wrong? Has anyone an idea
>>>> how I would work around the problem?
>>>>
>>>> Tom
>>>>
> 

Reply via email to