changeset 6249:7c2354578408

RT-28978 Consolidate/document handling of null values in javafx.scene.canvas.GraphicsContext Reviewed by: flar
author Martin Sladecek <martin.sladecek@oracle.com>
date Wed, 05 Feb 2014 08:35:28 +0100
parents 412d028f5f5f
children dfc3889169fc
files modules/graphics/src/main/java/javafx/scene/canvas/GraphicsContext.java modules/graphics/src/main/java/javafx/scene/image/PixelWriter.java modules/graphics/src/main/java/javafx/scene/image/WritableImage.java modules/graphics/src/test/java/javafx/scene/canvas/CanvasTest.java
diffstat 4 files changed, 239 insertions(+), 164 deletions(-) [+]
line wrap: on
line diff
--- a/modules/graphics/src/main/java/javafx/scene/canvas/GraphicsContext.java	Wed Feb 05 15:43:29 2014 +1300
+++ b/modules/graphics/src/main/java/javafx/scene/canvas/GraphicsContext.java	Wed Feb 05 08:35:28 2014 +0100
@@ -26,6 +26,7 @@
 package javafx.scene.canvas;
 
 import com.sun.javafx.geom.Arc2D;
+import com.sun.javafx.geom.IllegalPathStateException;
 import com.sun.javafx.geom.Path2D;
 import com.sun.javafx.geom.PathIterator;
 import com.sun.javafx.geom.transform.Affine2D;
@@ -332,6 +333,7 @@
     private void writePoly(double xPoints[], double yPoints[], int nPoints,
                            boolean close, byte command)
     {
+        if (xPoints == null || yPoints == null) return;
         GrowableDataBuffer buf = getBuffer();
         buf.putByte(NGCanvas.PATHSTART);
         int pos = 0;
@@ -358,7 +360,7 @@
     private void writeImage(Image img,
                             double dx, double dy, double dw, double dh)
     {
-        if (img.getProgress() < 1.0) return;
+        if (img == null || img.getProgress() < 1.0) return;
         Object platformImg = img.impl_getPlatformImage();
         if (platformImg == null) return;
         updateTransform();
@@ -371,7 +373,7 @@
                             double dx, double dy, double dw, double dh,
                             double sx, double sy, double sw, double sh)
     {
-        if (img.getProgress() < 1.0) return;
+        if (img == null || img.getProgress() < 1.0) return;
         Object platformImg = img.impl_getPlatformImage();
         if (platformImg == null) return;
         updateTransform();
@@ -387,6 +389,7 @@
     private void writeText(String text, double x, double y, double maxWidth,
                            byte command)
     {
+        if (text == null) return;
         updateTransform();
         GrowableDataBuffer buf = getBuffer();
         buf.putByte(command);
@@ -607,11 +610,12 @@
     /**
      * Concatenates the input with the current transform. Only 2D transforms are
      * supported. The only values used are the X and Y scaling, translation, and
-     * shearing components of a transform.
+     * shearing components of a transform. A {@code null} value is treated as identity.
      * 
-     * @param xform The affine to be concatenated with the current transform.
+     * @param xform The affine to be concatenated with the current transform or null.
      */
     public void transform(Affine xform) {
+        if (xform == null) return;
         scratchTX.setTransform(xform.getMxx(), xform.getMyx(),
                                xform.getMxy(), xform.getMyy(),
                                xform.getTx(), xform.getTy());
@@ -719,8 +723,9 @@
     private static Blend TMP_BLEND = new Blend(BlendMode.SRC_OVER); 
     /**
      * Sets the global blend mode.
+     * A {@code null} value will be ignored and the current value will remain unchanged.
      * 
-     * @param op the {@code BlendMode} that will be set.
+     * @param op the {@code BlendMode} that will be set or null.
      */
     public void setGlobalBlendMode(BlendMode op) {
         if (op != null && op != curState.blendop) {
@@ -745,11 +750,12 @@
     /**
      * Sets the current fill attribute. This method affects the paint used for any
      * method with "fill" in it. For Example, fillRect(...), fillOval(...).
+     * A {@code null} value will be ignored and the current value will remain unchanged.
      * 
-     * @param p The {@code Paint} to be used as the fill {@code Paint}.
+     * @param p The {@code Paint} to be used as the fill {@code Paint} or null.
      */
     public void setFill(Paint p) {
-        if (curState.fill != p) {
+        if (p != null && curState.fill != p) {
             curState.fill = p;
             writePaint(p, NGCanvas.FILL_PAINT);
         }
@@ -767,11 +773,12 @@
 
     /**
      * Sets the current stroke.
+     * A {@code null} value will be ignored and the current value will remain unchanged.
      * 
-     * @param p The Paint to be used as the stroke Paint.
+     * @param p The Paint to be used as the stroke Paint or null.
      */
     public void setStroke(Paint p) {
-        if (curState.stroke != p) {
+        if (p != null && curState.stroke != p) {
             curState.stroke = p;
             writePaint(p, NGCanvas.STROKE_PAINT);
         }
@@ -813,15 +820,13 @@
     }
 
     /**
-     * Sets the current stroke line cap. A {@code null} value will be ignored and the 
-     * current value will remain unchanged.
+     * Sets the current stroke line cap.
+     * A {@code null} value will be ignored and the current value will remain unchanged.
      * 
-     * @param cap {@code StrokeLineCap} with a value of Butt, Round, or Square.
-     * 
+     * @param cap {@code StrokeLineCap} with a value of Butt, Round, or Square or null.
      */
     public void setLineCap(StrokeLineCap cap) {
-        if (cap == null) return;
-        if (curState.linecap != cap) {
+        if (cap != null && curState.linecap != cap) {
             byte v;
             switch (cap) {
                 case BUTT: v = NGCanvas.CAP_BUTT; break;
@@ -844,14 +849,13 @@
     }
 
     /**
-     * Sets the current stroke line join. A {@code null} value will be ignored and 
-     * the current value will remain unchanged.
+     * Sets the current stroke line join.
+     * A {@code null} value will be ignored and the current value will remain unchanged.
      * 
-     * @param join {@code StrokeLineJoin} with a value of Miter, Bevel, or Round.
+     * @param join {@code StrokeLineJoin} with a value of Miter, Bevel, or Round or null.
      */
     public void setLineJoin(StrokeLineJoin join) {
-        if (join == null) return;
-        if (curState.linejoin != join) {
+        if (join != null && curState.linejoin != join) {
             byte v;
             switch (join) {
                 case MITER: v = NGCanvas.JOIN_MITER; break;
@@ -901,11 +905,12 @@
 
     /**
      * Sets the current Font.
+     * A {@code null} value will be ignored and the current value will remain unchanged.
      * 
-     * @param f the Font 
+     * @param f the Font or null.
      */
     public void setFont(Font f) {
-        if (curState.font != f) {
+        if (f != null && curState.font != f) {
             curState.font = f;
             GrowableDataBuffer buf = getBuffer();
             buf.putByte(NGCanvas.FONT);
@@ -924,7 +929,6 @@
 
     /**
      * Defines horizontal text alignment, relative to the text {@code x} origin.
-     * A {@code null} value will be ignored and the current value will remain unchanged.
      * <p>
      * Let horizontal bounds represent the logical width of a single line of
      * text. Where each line of text has a separate horizontal bounds.
@@ -941,12 +945,12 @@
      * Note: Canvas does not support line wrapping, therefore the text
      * alignment Justify is identical to left aligned text.
      * <p>
+     * A {@code null} value will be ignored and the current value will remain unchanged.
      * 
-     * @param align {@code TextAlignment} with values of Left, Center, Right.
+     * @param align {@code TextAlignment} with values of Left, Center, Right or null.
      */
     public void setTextAlign(TextAlignment align) {
-        if (align == null) return;
-        if (curState.textalign != align) {
+        if (align != null && curState.textalign != align) {
             byte a;
             switch (align) {
                 case LEFT: a = NGCanvas.ALIGN_LEFT; break;
@@ -971,14 +975,13 @@
     }
 
     /**
-     * Sets the current Text Baseline. A null value will be ignored and the 
-     * current value will remain unchanged.
+     * Sets the current Text Baseline.
+     * A {@code null} value will be ignored and the current value will remain unchanged.
      * 
-     * @param baseline {@code VPos} with values of Top, Center, Baseline, or Bottom
+     * @param baseline {@code VPos} with values of Top, Center, Baseline, or Bottom or null.
      */
     public void setTextBaseline(VPos baseline) {
-        if (baseline == null) return;
-        if (curState.textbaseline != baseline) {
+        if (baseline != null && curState.textbaseline != baseline) {
             byte b;
             switch (baseline) {
                 case TOP: b = NGCanvas.BASE_TOP; break;
@@ -1004,8 +1007,9 @@
     /**
      * Fills the given string of text at position x, y (0,0 at top left)
      * with the current fill paint attribute.
+     * A {@code null} text value will be ignored.
      * 
-     * @param text the string of text.
+     * @param text the string of text or null.
      * @param x position on the x axis.
      * @param y position on the y axis.
      */
@@ -1016,8 +1020,9 @@
     /**
      * draws the given string of text at position x, y (0,0 at top left)
      * with the current stroke paint attribute.
+     * A {@code null} text value will be ignored.
      * 
-     * @param text the string of text.
+     * @param text the string of text or null.
      * @param x position on the x axis.
      * @param y position on the y axis.
      */
@@ -1030,8 +1035,9 @@
      * 
      * If the width of the text extends past max width, then it will be sized
      * to fit.
+     * A {@code null} text value will be ignored.
      * 
-     * @param text the string of text.
+     * @param text the string of text or null.
      * @param x position on the x axis.
      * @param y position on the y axis.
      * @param maxWidth  maximum width the text string can have.
@@ -1046,8 +1052,9 @@
      * 
      * If the width of the text extends past max width, then it will be sized
      * to fit.
+     * A {@code null} text value will be ignored.
      * 
-     * @param text the string of text.
+     * @param text the string of text or null.
      * @param x position on the x axis.
      * @param y position on the y axis.
      * @param maxWidth  maximum width the text string can have.
@@ -1060,14 +1067,12 @@
 
     /**
      * Set the filling rule constant for determining the interior of the path.
-     * The value must be one of the following constants:
-     * {@code FillRile.EVEN_ODD} or {@code FillRule.NON_ZERO}.
-     * The default value is {@code FillRule.NON_ZERO}.
+     * A {@code null} value will be ignored and the current value will remain unchanged.
      *
-     * @defaultValue FillRule.NON_ZERO
+     * @param fillRule {@code FillRule} with a value of  Even_odd or Non_zero or null.
      */
      public void setFillRule(FillRule fillRule) {
-         if (curState.fillRule != fillRule) {
+         if (fillRule != null && curState.fillRule != fillRule) {
             byte b;
             if (fillRule == FillRule.EVEN_ODD) {
                 b = NGCanvas.FILL_RULE_EVEN_ODD;
@@ -1389,10 +1394,12 @@
     /**
      * Appends an SVG Path string to the current path. If there is no current 
      * path the string must then start with either type of move command.
-     * 
+     * A {@code null} value or incorrect SVG path will be ignored.
      * @param svgpath the SVG Path string.
+     *
      */
     public void appendSVGPath(String svgpath) {
+        if (svgpath == null) return;
         boolean prependMoveto = true;
         boolean skipMoveto = true;
         for (int i = 0; i < svgpath.length(); i++) {
@@ -1439,14 +1446,18 @@
         } else {
             skipMoveto = false;
         }
-        p2d.appendSVGPath(svgpath);
-        PathIterator pi = p2d.getPathIterator(curState.transform);
-        if (skipMoveto) {
-            // We need to delete the initial moveto and let the path
-            // extend from the actual existing geometry.
-            pi.next();
+        try {
+            p2d.appendSVGPath(svgpath);
+            PathIterator pi = p2d.getPathIterator(curState.transform);
+            if (skipMoveto) {
+                // We need to delete the initial moveto and let the path
+                // extend from the actual existing geometry.
+                pi.next();
+            }
+            path.append(pi, false);
+        } catch (IllegalArgumentException | IllegalPathStateException ex) {
+            //Ignore incorrect path
         }
-        path.append(pi, false);
     }
 
     /**
@@ -1579,7 +1590,7 @@
      * @param h the height of the arc.
      * @param startAngle the starting angle of the arc in degrees.
      * @param arcExtent the angular extent of the arc in degrees.
-     * @param closure closure type (Round, Chord, Open).
+     * @param closure closure type (Round, Chord, Open) or null.
      */
     public void fillArc(double x, double y, double w, double h,
                         double startAngle, double arcExtent, ArcType closure)
@@ -1593,14 +1604,14 @@
     /**
      * Strokes an Arc using the current stroke paint. A {@code null} ArcType or 
      * non positive width or height will cause the render command to be ignored.
-     * 
+     *
      * @param x the X coordinate of the arc.
      * @param y the Y coordinate of the arc.
      * @param w the width of the arc.
      * @param h the height of the arc.
      * @param startAngle the starting angle of the arc in degrees.
      * @param arcExtent arcExtent the angular extent of the arc in degrees.
-     * @param closure closure type (Round, Chord, Open).
+     * @param closure closure type (Round, Chord, Open) or null
      */
     public void strokeArc(double x, double y, double w, double h,
                         double startAngle, double arcExtent, ArcType closure)
@@ -1661,9 +1672,10 @@
 
     /**
      * Fills a polygon with the given points using the currently set fill paint.
+     * A {@code null} value for one of the arrays will be ignored and nothing will be drawn.
      * 
-     * @param xPoints array containing the x coordinates of the polygon's points.
-     * @param yPoints array containing the y coordinates of the polygon's points.
+     * @param xPoints array containing the x coordinates of the polygon's points or null.
+     * @param yPoints array containing the y coordinates of the polygon's points or null.
      * @param nPoints the number of points that make the polygon.
      */
     public void fillPolygon(double xPoints[], double yPoints[], int nPoints) {
@@ -1674,9 +1686,10 @@
 
     /**
      * Strokes a polygon with the given points using the currently set stroke paint.
+     * A {@code null} value for one of the arrays will be ignored and nothing will be drawn.
      * 
-     * @param xPoints array containing the x coordinates of the polygon's points.
-     * @param yPoints array containing the y coordinates of the polygon's points.
+     * @param xPoints array containing the x coordinates of the polygon's points or null.
+     * @param yPoints array containing the y coordinates of the polygon's points or null.
      * @param nPoints the number of points that make the polygon.
      */
     public void strokePolygon(double xPoints[], double yPoints[], int nPoints) {
@@ -1688,9 +1701,10 @@
     /**
      * Draws a polyline with the given points using the currently set stroke 
      * paint attribute.
+     * A {@code null} value for one of the arrays will be ignored and nothing will be drawn.
      * 
-     * @param xPoints array containing the x coordinates of the polyline's points.
-     * @param yPoints array containing the y coordinates of the polyline's points.
+     * @param xPoints array containing the x coordinates of the polyline's points or null.
+     * @param yPoints array containing the y coordinates of the polyline's points or null.
      * @param nPoints the number of points that make the polyline.
      */
     public void strokePolyline(double xPoints[], double yPoints[], int nPoints) {
@@ -1702,12 +1716,14 @@
     /**
      * Draws an image at the given x, y position using the width
      * and height of the given image.
+     * A {@code null} image value or an image still in progress will be ignored.
      * 
-     * @param img the image to be drawn.
+     * @param img the image to be drawn or null.
      * @param x the X coordinate on the destination for the upper left of the image.
      * @param y the Y coordinate on the destination for the upper left of the image.
      */
     public void drawImage(Image img, double x, double y) {
+        if (img == null) return;
         double sw = img.getWidth();
         double sh = img.getHeight();
         writeImage(img, x, y, sw, sh);
@@ -1716,8 +1732,9 @@
     /**
      * Draws an image into the given destination rectangle of the canvas. The
      * Image is scaled to fit into the destination rectagnle.
+     * A {@code null} image value or an image still in progress will be ignored.
      * 
-     * @param img the image to be drawn.
+     * @param img the image to be drawn or null.
      * @param x the X coordinate on the destination for the upper left of the image.
      * @param y the Y coordinate on the destination for the upper left of the image.
      * @param w the width of the destination rectangle. 
@@ -1730,8 +1747,9 @@
     /**
      * Draws the current source rectangle of the given image to the given 
      * destination rectangle of the Canvas.
+     * A {@code null} image value or an image still in progress will be ignored.
      * 
-     * @param img the image to be drawn.
+     * @param img the image to be drawn or null.
      * @param sx the source rectangle's X coordinate position.
      * @param sy the source rectangle's Y coordinate position.
      * @param sw the source rectangle's width.
@@ -1782,6 +1800,7 @@
 
                 @Override
                 public void setColor(int x, int y, Color c) {
+                    if (c == null) throw new NullPointerException("Color cannot be null");
                     int a = (int) Math.round(c.getOpacity() * 255.0);
                     int r = (int) Math.round(c.getRed() * 255.0);
                     int g = (int) Math.round(c.getGreen() * 255.0);
@@ -1859,6 +1878,8 @@
                               PixelFormat<T> pixelformat,
                               T buffer, int scan)
                 {
+                    if (pixelformat == null) throw new NullPointerException("PixelFormat cannot be null");
+                    if (buffer == null) throw new NullPointerException("Buffer cannot be null");
                     if (w <= 0 || h <= 0) return;
                     int offset = buffer.position();
                     int adjustments[] = checkBounds(x, y, w, h,
@@ -1888,6 +1909,8 @@
                                       PixelFormat<ByteBuffer> pixelformat,
                                       byte[] buffer, int offset, int scanlineStride)
                 {
+                    if (pixelformat == null) throw new NullPointerException("PixelFormat cannot be null");
+                    if (buffer == null) throw new NullPointerException("Buffer cannot be null");
                     if (w <= 0 || h <= 0) return;
                     int adjustments[] = checkBounds(x, y, w, h,
                                                     pixelformat, scanlineStride);
@@ -1915,6 +1938,8 @@
                                       PixelFormat<IntBuffer> pixelformat,
                                       int[] buffer, int offset, int scanlineStride)
                 {
+                    if (pixelformat == null) throw new NullPointerException("PixelFormat cannot be null");
+                    if (buffer == null) throw new NullPointerException("Buffer cannot be null");
                     if (w <= 0 || h <= 0) return;
                     int adjustments[] = checkBounds(x, y, w, h,
                                                     pixelformat, scanlineStride);
@@ -1941,6 +1966,7 @@
                 public void setPixels(int dstx, int dsty, int w, int h,
                                       PixelReader reader, int srcx, int srcy)
                 {
+                    if (reader == null) throw new NullPointerException("Reader cannot be null");
                     if (w <= 0 || h <= 0) return;
                     int adjustments[] = checkBounds(dstx, dsty, w, h, null, 0);
                     if (adjustments != null) {
@@ -1998,9 +2024,11 @@
 
     /**
      * Applies the given effect to the entire canvas.
-     * @param e the effect to apply onto the entire destination.
+     * A {@code null} value will be ignored.
+     * @param e the effect to apply onto the entire destination or null.
      */
     public void applyEffect(Effect e) {
+        if (e == null) return;
         GrowableDataBuffer buf = getBuffer();
         buf.putByte(NGCanvas.FX_APPLY_EFFECT);
         Effect effect = e.impl_copy();
--- a/modules/graphics/src/main/java/javafx/scene/image/PixelWriter.java	Wed Feb 05 15:43:29 2014 +1300
+++ b/modules/graphics/src/main/java/javafx/scene/image/PixelWriter.java	Wed Feb 05 08:35:28 2014 +0100
@@ -25,10 +25,11 @@
 
 package javafx.scene.image;
 
+import javafx.scene.paint.Color;
+
 import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.IntBuffer;
-import javafx.scene.paint.Color;
 
 /**
  * This interface defines methods for writing the pixel data of a
@@ -64,10 +65,12 @@
     /**
      * Stores pixel data for a {@link Color} into the specified coordinates
      * of the surface.
-     * 
+     *
      * @param x the X coordinate of the pixel color to write
      * @param y the Y coordinate of the pixel color to write
-     * @param c the Color to write
+     * @param c the Color to write or null
+     *
+     * @throws java.lang.NullPointerException if {@code color} is {@code null}
      */
     public void setColor(int x, int y, Color c);
 
@@ -86,7 +89,7 @@
      * Pixel data for adjacent rows will be read offset from each other
      * by the number of buffer data elements defined by
      * {@code scanlineStride}.
-     * 
+     *
      * @param x the X coordinate of the rectangular region to write
      * @param y the Y coordinate of the rectangular region to write
      * @param w the width of the rectangular region to write
@@ -98,6 +101,8 @@
      * @param scanlineStride the distance between the pixel data for the
      *        start of one row of data in the buffer to the start of the
      *        next row of data.
+     *
+     * @throws java.lang.NullPointerException if @{code pixelformat} or {@code buffer} is {@code null}
      */
     public <T extends Buffer>
         void setPixels(int x, int y, int w, int h,
@@ -120,7 +125,7 @@
      * Pixel data for adjacent rows will be read offset from each other
      * by the number of byte array elements defined by
      * {@code scanlineStride}.
-     * 
+     *
      * @param x the X coordinate of the rectangular region to write
      * @param y the Y coordinate of the rectangular region to write
      * @param w the width of the rectangular region to write
@@ -133,6 +138,8 @@
      * @param scanlineStride the distance between the pixel data for the
      *        start of one row of data in the buffer to the start of the
      *        next row of data
+     *
+     * @throws java.lang.NullPointerException if @{code pixelformat} or {@code buffer} is {@code null}
      */
     public void setPixels(int x, int y, int w, int h,
                           PixelFormat<ByteBuffer> pixelformat,
@@ -154,7 +161,7 @@
      * Pixel data for adjacent rows will be read offset from each other
      * by the number of int array elements defined by
      * {@code scanlineStride}.
-     * 
+     *
      * @param x the X coordinate of the rectangular region to write
      * @param y the Y coordinate of the rectangular region to write
      * @param w the width of the rectangular region to write
@@ -167,6 +174,8 @@
      * @param scanlineStride the distance between the pixel data for the
      *        start of one row of data in the buffer to the start of the
      *        next row of data
+     *
+     * @throws java.lang.NullPointerException if @{code pixelformat} or {@code buffer} is {@code null}
      */
     public void setPixels(int x, int y, int w, int h,
                           PixelFormat<IntBuffer> pixelformat,
@@ -188,7 +197,8 @@
      *         }
      *     }
      * </pre>
-     * 
+     *
+     *
      * @param dstx the X coordinate of the rectangular region to write
      * @param dsty the Y coordinate of the rectangular region to write
      * @param w the width of the rectangular region to write
@@ -197,6 +207,8 @@
      *        to write
      * @param srcx the X coordinate of the data to read from {@code reader}
      * @param srcy the Y coordinate of the data to read from {@code reader}
+     *
+     * @throws java.lang.NullPointerException if @{code reader} is {@code null}
      */
     public void setPixels(int dstx, int dsty, int w, int h,
                           PixelReader reader, int srcx, int srcy);
--- a/modules/graphics/src/main/java/javafx/scene/image/WritableImage.java	Wed Feb 05 15:43:29 2014 +1300
+++ b/modules/graphics/src/main/java/javafx/scene/image/WritableImage.java	Wed Feb 05 08:35:28 2014 +0100
@@ -28,12 +28,13 @@
 import com.sun.javafx.tk.ImageLoader;
 import com.sun.javafx.tk.PlatformImage;
 import com.sun.javafx.tk.Toolkit;
+import javafx.beans.NamedArg;
+import javafx.beans.property.ReadOnlyObjectProperty;
+import javafx.scene.paint.Color;
+
 import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.IntBuffer;
-import javafx.beans.NamedArg;
-import javafx.beans.property.ReadOnlyObjectProperty;
-import javafx.scene.paint.Color;
 
 /**
  * The {@code WritableImage} class represents a custom graphical image
@@ -172,6 +173,7 @@
 
                 @Override
                 public void setColor(int x, int y, Color c) {
+                    if (c == null) throw new NullPointerException("Color cannot be null");
                     int a = (int) Math.round(c.getOpacity() * 255);
                     int r = (int) Math.round(c.getRed()     * 255);
                     int g = (int) Math.round(c.getGreen()   * 255);
@@ -185,6 +187,8 @@
                                    PixelFormat<T> pixelformat,
                                    T buffer, int scanlineStride)
                 {
+                    if (pixelformat == null) throw new NullPointerException("PixelFormat cannot be null");
+                    if (buffer == null) throw new NullPointerException("Buffer cannot be null");
                     PlatformImage pimg = getWritablePlatformImage();
                     pimg.setPixels(x, y, w, h, pixelformat,
                                    buffer, scanlineStride);
@@ -196,6 +200,8 @@
                                       PixelFormat<ByteBuffer> pixelformat,
                                       byte buffer[], int offset, int scanlineStride)
                 {
+                    if (pixelformat == null) throw new NullPointerException("PixelFormat cannot be null");
+                    if (buffer == null) throw new NullPointerException("Buffer cannot be null");
                     PlatformImage pimg = getWritablePlatformImage();
                     pimg.setPixels(x, y, w, h, pixelformat,
                                    buffer, offset, scanlineStride);
@@ -207,6 +213,8 @@
                                       PixelFormat<IntBuffer> pixelformat,
                                       int buffer[], int offset, int scanlineStride)
                 {
+                    if (pixelformat == null) throw new NullPointerException("PixelFormat cannot be null");
+                    if (buffer == null) throw new NullPointerException("Buffer cannot be null");
                     PlatformImage pimg = getWritablePlatformImage();
                     pimg.setPixels(x, y, w, h, pixelformat,
                                    buffer, offset, scanlineStride);
@@ -217,6 +225,7 @@
                 public void setPixels(int writex, int writey, int w, int h,
                                       PixelReader reader, int readx, int ready)
                 {
+                    if (reader == null) throw new NullPointerException("Reader cannot be null");
                     PlatformImage pimg = getWritablePlatformImage();
                     pimg.setPixels(writex, writey, w, h, reader, readx, ready);
                     pixelsDirty();
--- a/modules/graphics/src/test/java/javafx/scene/canvas/CanvasTest.java	Wed Feb 05 15:43:29 2014 +1300
+++ b/modules/graphics/src/test/java/javafx/scene/canvas/CanvasTest.java	Wed Feb 05 08:35:28 2014 +0100
@@ -25,52 +25,46 @@
 
 package javafx.scene.canvas;
 
+import javafx.geometry.VPos;
 import javafx.scene.NodeTest;
 import javafx.scene.effect.BlendMode;
+import javafx.scene.image.ImageForTesting;
 import javafx.scene.paint.Color;
 import javafx.scene.shape.ArcType;
+import javafx.scene.shape.FillRule;
 import javafx.scene.shape.StrokeLineCap;
 import javafx.scene.shape.StrokeLineJoin;
+import javafx.scene.text.Font;
+import javafx.scene.text.TextAlignment;
 import javafx.scene.transform.Affine;
 import javafx.scene.transform.Rotate;
 import javafx.scene.transform.Transform;
+import org.junit.Before;
 import org.junit.Test;
-import static org.junit.Assert.*;
+
+import static org.junit.Assert.assertEquals;
 
 public class CanvasTest {
 
-    @Test public void testPropertyPropagation_visible() throws Exception {
-        final Canvas node = new Canvas();
-        NodeTest.testBooleanPropertyPropagation(node, "visible", false, true);
+    private Canvas canvas;
+    private GraphicsContext gc;
+
+    @Before
+    public void setUp() {
+        canvas = new Canvas();
+        gc = canvas.getGraphicsContext2D();
     }
 
-//    @Test public void testPropertyPropagation_x() throws Exception {
-//        final Canvas node = new Canvas();
-//        NodeTest.testDoublePropertyPropagation(node, "x", 100, 200);
-//    }
-//
-//    @Test public void testPropertyPropagation_y() throws Exception {
-//        final Canvas node = new Canvas();
-//        NodeTest.testDoublePropertyPropagation(node, "y", 100, 200);
-//    }
+    @Test public void testPropertyPropagation_visible() throws Exception {
+        NodeTest.testBooleanPropertyPropagation(canvas, "visible", false, true);
+    }
 
-    @Test public void testInitCanvas() throws Exception {
-        final Canvas node = new Canvas();
-    }
-    
-    @Test public void testGetGC() throws Exception {
-        Canvas node = new Canvas();
-        GraphicsContext gc = node.getGraphicsContext2D();
-    }
-    
     //maybe test doing stuff from different threads
     @Test public void testGetGC2() throws Exception {
-        Canvas node = new Canvas();
-        GraphicsContext gc = node.getGraphicsContext2D();
-        GraphicsContext gc2 = node.getGraphicsContext2D();
-        GraphicsContext gc3 = node.getGraphicsContext2D();
-        GraphicsContext gc4 = node.getGraphicsContext2D();
-        GraphicsContext gc5 = node.getGraphicsContext2D();
+        GraphicsContext gc2 = canvas.getGraphicsContext2D();
+        GraphicsContext gc3 = canvas.getGraphicsContext2D();
+        GraphicsContext gc4 = canvas.getGraphicsContext2D();
+        GraphicsContext gc5 = canvas.getGraphicsContext2D();
         assertEquals(gc,gc2);
         assertEquals(gc,gc3);
         assertEquals(gc,gc4);
@@ -79,96 +73,75 @@
     
     //basic tests make sure that the methods do not blow up.
     @Test public void testGCfillRect_basic() throws Exception {
-        Canvas node = new Canvas();
-        GraphicsContext gc = node.getGraphicsContext2D();
         gc.fillRect(0, 0, 1, 1);
     }
     
     @Test public void testGCfillOval_basic() throws Exception {
-        Canvas node = new Canvas();
-        GraphicsContext gc = node.getGraphicsContext2D();
         gc.fillOval(0, 0, 1, 1);
     }
         
     @Test public void testGCfillRoundRect_basic() throws Exception {
-        Canvas node = new Canvas();
-        GraphicsContext gc = node.getGraphicsContext2D();
         gc.fillRoundRect(0, 0, 1, 1, 2, 2);
     }
     
     @Test public void testGCfillText_basic() throws Exception {
-        Canvas node = new Canvas();
-        GraphicsContext gc = node.getGraphicsContext2D();
         gc.fillText("Test", 0, 0);
+        gc.fillText("Test", 0, 0, 0);
+        gc.fillText("", 0, 0, 0);
         gc.fillText("", 0, 0);
         gc.fillText(null, 0, 0);
+        gc.fillText(null, 0, 0, 0);
     }
     
     @Test public void testGCfillPolygon_basic() throws Exception {
-        Canvas node = new Canvas();
-        GraphicsContext gc = node.getGraphicsContext2D();
         double[] xPoints = {0.0,10.0};
         double[] yPoints = {0.0,10.0};        
         gc.fillPolygon( xPoints, yPoints, 2);
+        gc.fillPolygon( xPoints, null, 2);
+        gc.fillPolygon( null, yPoints, 2);
     }
     
     @Test public void testGCfillArc_basic() throws Exception {
-        Canvas node = new Canvas();
-        GraphicsContext gc = node.getGraphicsContext2D();
-        double[] xPoints = {0.0,10.0};
-        double[] yPoints = {0.0,10.0};        
-        gc.fillArc(10, 10, 100, 100, 0, 40, ArcType.OPEN); 
+        gc.fillArc(10, 10, 100, 100, 0, 40, ArcType.OPEN);
         gc.fillArc(10, 10, 100, 100, 0, 360, ArcType.CHORD); 
         gc.fillArc(10, 10, 100, 100, 0, 361, ArcType.ROUND); 
+        gc.fillArc(10, 10, 100, 100, 0, 361, null);
     }
     
     @Test public void testGCdrawRect_basic() throws Exception {
-        Canvas node = new Canvas();
-        GraphicsContext gc = node.getGraphicsContext2D();
         gc.rect(0, 0, 1, 1);
     }
     
     @Test public void testGCdrawOval_basic() throws Exception {
-        Canvas node = new Canvas();
-        GraphicsContext gc = node.getGraphicsContext2D();
         gc.strokeOval(0, 0, 1, 1);
     }
         
     @Test public void testGCdrawRoundRect_basic() throws Exception {
-        Canvas node = new Canvas();
-        GraphicsContext gc = node.getGraphicsContext2D();
         gc.strokeRoundRect(0, 0, 1, 1, 2, 2);
     }
     
     @Test public void testGCstrokeText_basic() throws Exception {
-        Canvas node = new Canvas();
-        GraphicsContext gc = node.getGraphicsContext2D();
         gc.strokeText("Test", 0, 0);
         gc.strokeText("", 0, 0);
         gc.strokeText(null, 0, 0);
     }
     
     @Test public void testGCdrawPolygon_basic() throws Exception {
-        Canvas node = new Canvas();
-        GraphicsContext gc = node.getGraphicsContext2D();
         double[] xPoints = {0.0,10.0};
         double[] yPoints = {0.0,10.0};        
         gc.strokePolygon( xPoints, yPoints, 2);
+        gc.strokePolygon( null, yPoints, 2);
+        gc.strokePolygon( xPoints, null, 2);
     }
-    
+
     @Test public void testGCdrawArc_basic() throws Exception {
-        Canvas node = new Canvas();
-        GraphicsContext gc = node.getGraphicsContext2D();
-        double[] xPoints = {0.0,10.0};
-        double[] yPoints = {0.0,10.0};        
-        gc.strokeArc(10, 10, 100, 100, 0, 40, ArcType.OPEN); 
+        gc.strokeArc(10, 10, 100, 100, 0, 40, ArcType.OPEN);
         gc.strokeArc(10, 10, 100, 100, 0, 360, ArcType.CHORD); 
         gc.strokeArc(10, 10, 100, 100, 0, 361, ArcType.ROUND); 
+        gc.strokeArc(10, 10, 100, 100, 0, 361, null);
     }
     
     @Test public void testGCfillPath_basic() throws Exception {
-        Canvas node = new Canvas();
-        GraphicsContext gc = node.getGraphicsContext2D();
         gc.arcTo(0, 0, 5, 5, 5);
         gc.moveTo(50, 50);
         gc.lineTo(100, 100);
@@ -182,8 +155,6 @@
     }
     
     @Test public void testGCclip_basic() throws Exception {
-        Canvas node = new Canvas();
-        GraphicsContext gc = node.getGraphicsContext2D();
         gc.beginPath();
         gc.moveTo(50, 50);
         gc.lineTo(100, 100);
@@ -194,8 +165,6 @@
     }
     
     @Test public void testGCfillDrawPath_basic() throws Exception {
-        Canvas node = new Canvas();
-        GraphicsContext gc = node.getGraphicsContext2D();
         gc.beginPath();
         gc.moveTo(50, 50);
         gc.lineTo(100, 100);
@@ -209,9 +178,6 @@
     
     
     @Test public void testGCState_Translate() throws Exception {
-        Canvas node = new Canvas();
-        GraphicsContext gc = node.getGraphicsContext2D();
-        
         gc.translate(50, 50);
         Affine result = gc.getTransform();
         Affine expected = new Affine();
@@ -223,9 +189,6 @@
     }
     
     @Test public void testGCState_Scale() throws Exception {
-        Canvas node = new Canvas();
-        GraphicsContext gc = node.getGraphicsContext2D();
-        
         gc.scale(3, 3);
         Affine result = gc.getTransform();
         Affine expected = new Affine();
@@ -237,9 +200,6 @@
     }
 
     @Test public void testGCState_Rotate() throws Exception {
-        Canvas node = new Canvas();
-        GraphicsContext gc = node.getGraphicsContext2D();
-        
         gc.rotate(45.0);
         Affine result = gc.getTransform();
         
@@ -249,10 +209,6 @@
     }
 
     @Test public void testGCState_getTransform() throws Exception {
-        Canvas node = new Canvas();
-        GraphicsContext gc = node.getGraphicsContext2D();
-        
-
         Affine expected = new Affine();
         gc.setTransform(expected);
         Affine result = gc.getTransform();
@@ -268,9 +224,6 @@
     }
 
     @Test public void testGCState_FillStrokeSaveRestore() throws Exception {
-        Canvas node = new Canvas();
-        GraphicsContext gc = node.getGraphicsContext2D();
-        
         Affine expected = new Affine();
         gc.setTransform(expected);
         Affine result = gc.getTransform();
@@ -294,10 +247,52 @@
         assertMatrix(result, expected);
     }
 
+    @Test public void testGCState_SetStroke() {
+        gc.setStroke(Color.RED);
+        assertEquals(Color.RED, gc.getStroke());
+        gc.setStroke(null);
+        assertEquals(Color.RED, gc.getStroke());
+    }
+
+    @Test public void testGCState_Fill_Null() {
+        gc.setFill(Color.BLACK);
+        assertEquals(Color.BLACK, gc.getFill());
+        gc.setFill(Color.RED);
+        assertEquals(gc.getFill(), Color.RED);
+        gc.setFill(null);
+        assertEquals(gc.getFill(), Color.RED);
+    }
+
+    @Test public void testGCState_FillRule_Null() {
+        gc.setFillRule(FillRule.EVEN_ODD);
+        assertEquals(FillRule.EVEN_ODD, gc.getFillRule());
+        gc.setFillRule(null);
+        assertEquals(FillRule.EVEN_ODD, gc.getFillRule());
+    }
+
+    @Test public void testGCState_Font_Null() {
+        Font f = new Font(10);
+        gc.setFont(f);
+        assertEquals(f, gc.getFont());
+        gc.setFont(null);
+        assertEquals(f, gc.getFont());
+    }
+
+    @Test public void testGCState_TextBaseline_Null() {
+        gc.setTextBaseline(VPos.BASELINE);
+        assertEquals(VPos.BASELINE, gc.getTextBaseline());
+        gc.setTextBaseline(null);
+        assertEquals(VPos.BASELINE, gc.getTextBaseline());
+    }
+
+    @Test public void testGCState_TextAlign_Null() {
+        gc.setTextAlign(TextAlignment.JUSTIFY);
+        assertEquals(TextAlignment.JUSTIFY, gc.getTextAlign());
+        gc.setTextAlign(null);
+        assertEquals(TextAlignment.JUSTIFY, gc.getTextAlign());
+    }
+
     @Test public void testGCState_Line() throws Exception {
-        Canvas node = new Canvas();
-        GraphicsContext gc = node.getGraphicsContext2D();
-        
         gc.setLineCap(StrokeLineCap.BUTT);
         gc.setLineJoin(StrokeLineJoin.MITER);
         gc.setLineWidth(5);
@@ -322,9 +317,6 @@
 
     @Test
     public void testGCState_LineCapNull() throws Exception {
-        Canvas node = new Canvas();
-        GraphicsContext gc = node.getGraphicsContext2D();
-
         gc.setLineCap(StrokeLineCap.BUTT);
         gc.setLineCap(null);
         assertEquals(gc.getLineCap(), StrokeLineCap.BUTT);
@@ -338,9 +330,6 @@
 
     @Test
     public void testGCState_LineJoinNull() throws Exception {
-        Canvas node = new Canvas();
-        GraphicsContext gc = node.getGraphicsContext2D();
-
         gc.setLineJoin(StrokeLineJoin.BEVEL);
         gc.setLineJoin(null);
         assertEquals(gc.getLineJoin(), StrokeLineJoin.BEVEL);
@@ -353,9 +342,6 @@
     }
 
     @Test public void testGCState_BlendMode() throws Exception {
-        Canvas node = new Canvas();
-        GraphicsContext gc = node.getGraphicsContext2D();
-        
         gc.setGlobalBlendMode(BlendMode.ADD);
         gc.setGlobalAlpha(0);
         
@@ -370,6 +356,46 @@
         assertEquals(0, gc.getGlobalAlpha(), 0.000001);       
     }
 
+    @Test public void testGCState_BlendMode_Null() {
+        gc.setGlobalBlendMode(BlendMode.ADD);
+        assertEquals(BlendMode.ADD, gc.getGlobalBlendMode());
+        gc.setGlobalBlendMode(null);
+        assertEquals(BlendMode.ADD, gc.getGlobalBlendMode());
+    }
+
+    @Test public void testGCappendSVGPath_Null() {
+        gc.appendSVGPath("m 0 0");
+        gc.appendSVGPath("Q 150 -300 300 0");
+        gc.appendSVGPath(null);
+    }
+
+    @Test public void testGCappendSVGPath_IncorrectPath() {
+        gc.appendSVGPath("Q 150 -300 300 0"); // No move at the beginning
+    }
+
+    @Test public void testGCappendSVGPath_IncorrectPath2() {
+        gc.appendSVGPath("F 150"); // No move at the beginning
+    }
+
+    @Test public void testGCapplyEffect_Null() {
+        gc.applyEffect(null);
+    }
+
+    @Test public void testGCdrawImage_Null() {
+        gc.drawImage(null, 0 ,0);
+        gc.drawImage(null, 0 ,0, 100, 100);
+        gc.drawImage(null, 0, 0, 100, 100, 0, 0, 100, 100);
+    }
+
+    @Test public void testGCdrawImage_InProgress() {
+        ImageForTesting image = new ImageForTesting("http://something.png", false);
+        image.updateProgress(0.5);
+
+        gc.drawImage(image, 0 ,0);
+        gc.drawImage(image, 0 ,0, 100, 100);
+        gc.drawImage(image, 0, 0, 100, 100, 0, 0, 100, 100);
+    }
+
     public static void assertMatrix(Transform expected,
             Transform result) {
         assertEquals(expected.getMxx(), result.getMxx(), 0.00001);