/*
 * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

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;
import com.sun.javafx.geom.transform.NoninvertibleTransformException;
import com.sun.javafx.image.*;
import com.sun.javafx.image.impl.ByteBgraPre;
import com.sun.javafx.sg.prism.GrowableDataBuffer;
import com.sun.javafx.sg.prism.NGCanvas;
import com.sun.javafx.scene.text.FontHelper;
import com.sun.javafx.tk.Toolkit;
import com.sun.scenario.effect.EffectHelper;
import javafx.geometry.NodeOrientation;
import javafx.geometry.VPos;
import javafx.scene.effect.Blend;
import javafx.scene.effect.BlendMode;
import javafx.scene.effect.Effect;
import javafx.scene.image.Image;
import javafx.scene.image.PixelFormat;
import javafx.scene.image.PixelReader;
import javafx.scene.image.PixelWriter;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
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 java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.Arrays;
import java.util.LinkedList;
import javafx.scene.text.FontSmoothingType;

This class is used to issue draw calls to a Canvas using a buffer.

Each call pushes the necessary parameters onto the buffer where they will be later rendered onto the image of the Canvas node by the rendering thread at the end of a pulse.

A Canvas only contains one GraphicsContext, and only one buffer. If it is not attached to any scene, then it can be modified by any thread, as long as it is only used from one thread at a time. Once a Canvas node is attached to a scene, it must be modified on the JavaFX Application Thread.

Calling any method on the GraphicsContext is considered modifying its corresponding Canvas and is subject to the same threading rules.

A GraphicsContext also manages a stack of state objects that can be saved or restored at anytime.

The GraphicsContext maintains the following rendering attributes which affect various subsets of the rendering methods:

List of Rendering Attributes
Attribute Save/Restore? Default value Description
Common Rendering Attributes
Clip Yes No clipping An anti-aliased intersection of various clip paths to which rendering is restricted.
Global Alpha Yes 1.0 An opacity value that controls the visibility or fading of each rendering operation.
Global Blend Mode Yes SRC_OVER A BlendMode enum value that controls how pixels from each rendering operation are composited into the existing image.
Transform Yes Identity A 3x2 2D affine transformation matrix that controls how coordinates are mapped onto the logical pixels of the canvas image.
Effect Yes null An Effect applied individually to each rendering operation.
Fill Attributes
Fill Paint Yes BLACK The Paint to be applied to the interior of shapes in a fill operation.
Stroke Attributes
Stroke Paint Yes BLACK The Paint to be applied to the boundary of shapes in a stroke operation.
Line Width Yes 1.0 The width of the stroke applied to the boundary of shapes in a stroke operation.
Line Cap Yes SQUARE The style of the end caps applied to the beginnings and ends of each dash and/or subpath in a stroke operation.
Line Join Yes MITER The style of the joins applied between individual segments in the boundary paths of shapes in a stroke operation.
Miter Limit Yes 10.0 The ratio limit of how far a MITER line join may extend in the direction of a sharp corner between segments in the boundary path of a shape, relative to the line width, before it is truncated to a BEVEL join in a stroke operation.
Dashes Yes null The array of dash lengths to be applied to the segments in the boundary of shapes in a stroke operation.
Dash Offset Yes 0.0 The distance offset into the array of dash lengths at which to start the dashing of the segments in the boundary of shapes in a stroke operation.
Text Attributes
Font Yes Default Font The font used for all fill and stroke text operations.
Text Align Yes LEFT The horizontal alignment of text with respect to the X coordinate specified in the text operation.
Text Baseline Yes BASELINE The vertical position of the text relative to the Y coordinate specified in the text operation.
Font Smoothing Yes GRAY The type of smoothing (antialiasing) applied to the glyphs in the font for all fill text operations.
Path Attributes
Current Path No Empty path The path constructed using various path construction methods to be used in various path filling, stroking, or clipping operations.
Fill Rule Yes NON_ZERO The method used to determine the interior of paths for a path fill or clip operation.
Image Attributes
Image Smoothing Yes true A boolean state which enables or disables image smoothing for drawImage(all forms).

The various rendering methods on the GraphicsContext use the following sets of rendering attributes:

Rendering Attributes Table
Method Common Rendering Attributes Fill Attributes Stroke Attributes Text Attributes Path Attributes Image Attributes
Basic Shape Rendering
fillRect(), fillRoundRect(), fillOval(), fillArc() Yes Yes No No No No
strokeLine(), strokeRect(), strokeRoundRect(), strokeOval(), strokeArc() Yes No Yes No No No
clearRect() Yes [1] No No No No No
fillPolygon() Yes Yes No No Yes [2] No
strokePolygon(), strokePolyline() Yes No Yes No No No
[1] Only the Transform, Clip, and Effect apply to clearRect()
[2] Only the Fill Rule applies to fillPolygon(), the current path is left unchanged
Text Rendering
fillText(), fillText(with maxWidth) Yes Yes No Yes [3] No No
strokeText(), strokeText(with maxWidth) Yes No Yes Yes [3] No No
[3] The Font Smoothing attribute only applies to filled text
Path Rendering
beginPath(), moveTo(), lineTo(), quadraticCurveTo(), bezierCurveTo(), arc(), arcTo(), appendSVGPath(), closePath(), rect() Yes [4] No No No No No
fill() Yes [4] Yes No No Yes No
stroke() Yes [4] No Yes No Yes [5] No
clip() No No No No Yes No
[4] Transform applied only during path construction
[5] Fill Rule only used for fill() and clip()
Image Rendering
drawImage(all forms) Yes No No No No Yes
Miscellaneous
applyEffect(), PixelWriter methods No No No No No No

Example:

import javafx.scene.*;
import javafx.scene.paint.*;
import javafx.scene.canvas.*;
Group root = new Group();
Scene s = new Scene(root, 300, 300, Color.BLACK);
final Canvas canvas = new Canvas(250,250);
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.setFill(Color.BLUE);
gc.fillRect(75,75,100,100);
root.getChildren().add(canvas);
See Also:
Since:JavaFX 2.2
/** * This class is used to issue draw calls to a {@link Canvas} using a buffer. * <p> * Each call pushes the necessary parameters onto the buffer * where they will be later rendered onto the image of the {@code Canvas} node * by the rendering thread at the end of a pulse. * <p> * A {@code Canvas} only contains one {@code GraphicsContext}, and only one buffer. * If it is not attached to any scene, then it can be modified by any thread, * as long as it is only used from one thread at a time. Once a {@code Canvas} * node is attached to a scene, it must be modified on the JavaFX Application * Thread. * <p> * Calling any method on the {@code GraphicsContext} is considered modifying * its corresponding {@code Canvas} and is subject to the same threading * rules. * <p> * A {@code GraphicsContext} also manages a stack of state objects that can * be saved or restored at anytime. * <p> * The {@code GraphicsContext} maintains the following rendering attributes * which affect various subsets of the rendering methods: * <table class="overviewSummary" style="width:80%; margin-left:auto; margin-right:auto"> * <caption>List of Rendering Attributes</caption> * <tr> * <th class="colLast" style="width:15%" scope="col">Attribute</th> * <th class="colLast" style="width:10%; text-align:center" scope="col">Save/Restore?</th> * <th class="colLast" style="width:10%; text-align:center" scope="col">Default value</th> * <th class="colLast" scope="col">Description</th> * </tr> * <tr><th colspan="3" scope="row"><a id="comm-attr">Common Rendering Attributes</a></th></tr> * <tr class="rowColor"> * <th scope="row" class="colLast" style="width:15%">{@link #clip() Clip}</th> * <td class="colLast" style="width:10%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:10%; text-align:center">No clipping</td> * <td class="colLast"> * An anti-aliased intersection of various clip paths to which rendering * is restricted. * </td></tr> * <tr class="altColor"> * <th scope="row" class="colLast" style="width:15%">{@link #setGlobalAlpha(double) Global Alpha}</th> * <td class="colLast" style="width:10%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:10%; text-align:center">{@code 1.0}</td> * <td class="colLast"> * An opacity value that controls the visibility or fading of each rendering * operation. * </td></tr> * <tr class="rowColor"> * <th scope="row" class="colLast" style="width:15%">{@link #setGlobalBlendMode(javafx.scene.effect.BlendMode) Global Blend Mode}</th> * <td class="colLast" style="width:10%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:10%; text-align:center">{@link BlendMode#SRC_OVER SRC_OVER}</td> * <td class="colLast"> * A {@link BlendMode} enum value that controls how pixels from each rendering * operation are composited into the existing image. * </td></tr> * <tr class="altColor"> * <th scope="row" class="colLast" style="width:15%">{@link #setTransform(javafx.scene.transform.Affine) Transform}</th> * <td class="colLast" style="width:10%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:10%; text-align:center">{@code Identity}</td> * <td class="colLast"> * A 3x2 2D affine transformation matrix that controls how coordinates are * mapped onto the logical pixels of the canvas image. * </td></tr> * <tr class="rowColor"> * <th scope="row" class="colLast" style="width:15%">{@link #setEffect(javafx.scene.effect.Effect) Effect}</th> * <td class="colLast" style="width:10%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:10%; text-align:center">{@code null}</td> * <td class="colLast"> * An {@link Effect} applied individually to each rendering operation. * </td></tr> * <tr><th colspan="3" scope="row"><a id="fill-attr">Fill Attributes</a></th></tr> * <tr class="rowColor"> * <th scope="row" class="colLast" style="width:15%">{@link #setFill(javafx.scene.paint.Paint) Fill Paint}</th> * <td class="colLast" style="width:10%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:10%; text-align:center">{@link Color#BLACK BLACK}</td> * <td class="colLast"> * The {@link Paint} to be applied to the interior of shapes in a * fill operation. * </td></tr> * <tr><th colspan="3" scope="row"><a id="strk-attr">Stroke Attributes</a></th></tr> * <tr class="rowColor"> * <th scope="row" class="colLast" style="width:15%">{@link #setStroke(javafx.scene.paint.Paint) Stroke Paint}</th> * <td class="colLast" style="width:10%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:10%; text-align:center">{@link Color#BLACK BLACK}</td> * <td class="colLast"> * The {@link Paint} to be applied to the boundary of shapes in a * stroke operation. * </td></tr> * <tr class="altColor"> * <th scope="row" class="colLast" style="width:15%">{@link #setLineWidth(double) Line Width}</th> * <td class="colLast" style="width:10%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:10%; text-align:center">{@code 1.0}</td> * <td class="colLast"> * The width of the stroke applied to the boundary of shapes in a * stroke operation. * </td></tr> * <tr class="rowColor"> * <th scope="row" class="colLast" style="width:15%">{@link #setLineCap(javafx.scene.shape.StrokeLineCap) Line Cap}</th> * <td class="colLast" style="width:10%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:10%; text-align:center">{@link StrokeLineCap#SQUARE SQUARE}</td> * <td class="colLast"> * The style of the end caps applied to the beginnings and ends of each * dash and/or subpath in a stroke operation. * </td></tr> * <tr class="altColor"> * <th scope="row" class="colLast" style="width:15%">{@link #setLineJoin(javafx.scene.shape.StrokeLineJoin) Line Join}</th> * <td class="colLast" style="width:10%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:10%; text-align:center">{@link StrokeLineJoin#MITER MITER}</td> * <td class="colLast"> * The style of the joins applied between individual segments in the boundary * paths of shapes in a stroke operation. * </td></tr> * <tr class="rowColor"> * <th scope="row" class="colLast" style="width:15%">{@link #setMiterLimit(double) Miter Limit}</th> * <td class="colLast" style="width:10%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:10%; text-align:center">{@code 10.0}</td> * <td class="colLast"> * The ratio limit of how far a {@link StrokeLineJoin#MITER MITER} line join * may extend in the direction of a sharp corner between segments in the * boundary path of a shape, relative to the line width, before it is truncated * to a {@link StrokeLineJoin#BEVEL BEVEL} join in a stroke operation. * </td></tr> * <tr class="altColor"> * <th scope="row" class="colLast" style="width:15%">{@link #setLineDashes(double...) Dashes}</th> * <td class="colLast" style="width:10%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:10%; text-align:center">{@code null}</td> * <td class="colLast"> * The array of dash lengths to be applied to the segments in the boundary * of shapes in a stroke operation. * </td></tr> * <tr class="rowColor"> * <th scope="row" class="colLast" style="width:15%">{@link #setLineDashOffset(double) Dash Offset}</th> * <td class="colLast" style="width:10%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:10%; text-align:center">{@code 0.0}</td> * <td class="colLast"> * The distance offset into the array of dash lengths at which to start the * dashing of the segments in the boundary of shapes in a stroke operation. * </td></tr> * <tr><th colspan="3" scope="row"><a id="text-attr">Text Attributes</a></th></tr> * <tr class="rowColor"> * <th scope="row" class="colLast" style="width:15%">{@link #setFont(javafx.scene.text.Font) Font}</th> * <td class="colLast" style="width:10%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:10%; text-align:center">{@link Font#getDefault() Default Font}</td> * <td class="colLast"> * The font used for all fill and stroke text operations. * </td></tr> * <tr class="altColor"> * <th scope="row" class="colLast" style="width:15%">{@link #setTextAlign(javafx.scene.text.TextAlignment) Text Align}</th> * <td class="colLast" style="width:10%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:10%; text-align:center">{@link TextAlignment#LEFT LEFT}</td> * <td class="colLast"> * The horizontal alignment of text with respect to the {@code X} coordinate * specified in the text operation. * </td></tr> * <tr class="rowColor"> * <th scope="row" class="colLast" style="width:15%">{@link #setTextBaseline(javafx.geometry.VPos) Text Baseline}</th> * <td class="colLast" style="width:10%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:10%; text-align:center">{@link VPos#BASELINE BASELINE}</td> * <td class="colLast"> * The vertical position of the text relative to the {@code Y} coordinate * specified in the text operation. * </td></tr> * <tr class="altColor"> * <th scope="row" class="colLast" style="width:15%">{@link #setFontSmoothingType(javafx.scene.text.FontSmoothingType) Font Smoothing}</th> * <td class="colLast" style="width:10%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:10%; text-align:center">{@link FontSmoothingType#GRAY GRAY}</td> * <td class="colLast"> * The type of smoothing (antialiasing) applied to the glyphs in the font * for all fill text operations. * </td></tr> * <tr><th colspan="3" scope="row"><a id="path-attr">Path Attributes</a></th></tr> * <tr class="rowColor"> * <th scope="row" class="colLast" style="width:15%">{@link #beginPath() Current Path}</th> * <td class="colLast" style="width:10%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:10%; text-align:center">Empty path</td> * <td class="colLast"> * The path constructed using various path construction methods to be used * in various path filling, stroking, or clipping operations. * </td></tr> * <tr class="altColor"> * <th scope="row" class="colLast" style="width:15%">{@link #setFillRule(javafx.scene.shape.FillRule) Fill Rule}</th> * <td class="colLast" style="width:10%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:10%; text-align:center">{@link FillRule#NON_ZERO NON_ZERO}</td> * <td class="colLast"> * The method used to determine the interior of paths for a path fill or * clip operation. * </td></tr> * <tr><th colspan="3" scope="row"><a id="image-attr">Image Attributes</a></th></tr> * <tr class="rowColor"> * <th scope="row" class="colLast" style="width:15%">{@link #setImageSmoothing(boolean) Image Smoothing}</th> * <td class="colLast" style="width:10%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:10%; text-align:center">{@code true}</td> * <td class="colLast"> * A boolean state which enables or disables image smoothing for * {@link #drawImage(javafx.scene.image.Image, double, double) drawImage(all forms)}. * </td></tr> * </table> * <p> * <a id="attr-ops-table"> * The various rendering methods on the {@code GraphicsContext} use the * following sets of rendering attributes: * </a> * <table class="overviewSummary" style="width:80%; margin-left:auto; margin-right:auto"> * <caption>Rendering Attributes Table</caption> * <tr> * <th scope="col" class="colLast" style="width:22%">Method</th> * <th scope="col" class="colLast" style="width:13%; text-align:center"><a href="#comm-attr">Common Rendering Attributes</a></th> * <th scope="col" class="colLast" style="width:13%; text-align:center"><a href="#fill-attr">Fill Attributes</a></th> * <th scope="col" class="colLast" style="width:13%; text-align:center"><a href="#strk-attr">Stroke Attributes</a></th> * <th scope="col" class="colLast" style="width:13%; text-align:center"><a href="#text-attr">Text Attributes</a></th> * <th scope="col" class="colLast" style="width:13%; text-align:center"><a href="#path-attr">Path Attributes</a></th> * <th scope="col" class="colLast" style="width:13%; text-align:center"><a href="#image-attr">Image Attributes</a></th> * </tr> * <tr><th colspan="1" scope="row">Basic Shape Rendering</th></tr> * <tr class="rowColor"> * <th scope="row" class="colLast" style="width:22%"> * {@link #fillRect(double, double, double, double) fillRect()}, * {@link #fillRoundRect(double, double, double, double, double, double) fillRoundRect()}, * {@link #fillOval(double, double, double, double) fillOval()}, * {@link #fillArc(double, double, double, double, double, double, javafx.scene.shape.ArcType) fillArc()} * </th> * <td class="colLast" style="width:13%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:13%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * </tr> * <tr class="altColor"> * <th scope="row" class="colLast" style="width:22%"> * {@link #strokeLine(double, double, double, double) strokeLine()}, * {@link #strokeRect(double, double, double, double) strokeRect()}, * {@link #strokeRoundRect(double, double, double, double, double, double) strokeRoundRect()}, * {@link #strokeOval(double, double, double, double) strokeOval()}, * {@link #strokeArc(double, double, double, double, double, double, javafx.scene.shape.ArcType) strokeArc()} * </th> * <td class="colLast" style="width:13%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * </tr> * <tr class="rowColor"> * <th scope="row" class="colLast" style="width:22%"> * {@link #clearRect(double, double, double, double) clearRect()} * </th> * <td class="colLast" style="width:13%; text-align:center; color:#0c0">Yes <a href="#base-fn-1">[1]</a></td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * </tr> * <tr class="altColor"> * <th scope="row" class="colLast" style="width:22%"> * {@link #fillPolygon(double[], double[], int) fillPolygon()} * </th> * <td class="colLast" style="width:13%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:13%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#0c0">Yes <a href="#base-fn-2">[2]</a></td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * </tr> * <tr class="rowColor"> * <th scope="row" class="colLast" style="width:22%"> * {@link #strokePolygon(double[], double[], int) strokePolygon()}, * {@link #strokePolyline(double[], double[], int) strokePolyline()} * </th> * <td class="colLast" style="width:13%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * </tr> * <tr><th scope="row" colspan="6"> * <a id="base-fn-1">[1]</a> Only the Transform, Clip, and Effect apply to clearRect()<br> * <a id="base-fn-2">[2]</a> Only the Fill Rule applies to fillPolygon(), the current path is left unchanged * </th></tr> * <tr><th colspan="1" scope="row">Text Rendering</th></tr> * <tr class="rowColor"> * <th scope="row" class="colLast" style="width:22%"> * {@link #fillText(java.lang.String, double, double) fillText()}, * {@link #fillText(java.lang.String, double, double, double) fillText(with maxWidth)} * </th> * <td class="colLast" style="width:13%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:13%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#0c0">Yes <a href="#text-fn-3">[3]</a></td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * </tr> * <tr class="altColor"> * <th scope="row" class="colLast" style="width:22%"> * {@link #strokeText(java.lang.String, double, double) strokeText()}, * {@link #strokeText(java.lang.String, double, double, double) strokeText(with maxWidth)} * </th> * <td class="colLast" style="width:13%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:13%; text-align:center; color:#0c0">Yes <a href="#text-fn-3">[3]</a></td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * </tr> * <tr><th scope="row" colspan="6"> * <a id="text-fn-3">[3]</a> The Font Smoothing attribute only applies to filled text * </th></tr> * <tr><th colspan="1" scope="row">Path Rendering</th></tr> * <tr class="rowColor"> * <th scope="row" class="colLast" style="width:22%"> * {@link #beginPath() beginPath()}, * {@link #moveTo(double, double) moveTo()}, * {@link #lineTo(double, double) lineTo()}, * {@link #quadraticCurveTo(double, double, double, double) quadraticCurveTo()}, * {@link #bezierCurveTo(double, double, double, double, double, double) bezierCurveTo()}, * {@link #arc(double, double, double, double, double, double) arc()}, * {@link #arcTo(double, double, double, double, double) arcTo()}, * {@link #appendSVGPath(java.lang.String) appendSVGPath()}, * {@link #closePath() closePath()}, * {@link #rect(double, double, double, double) rect()} * </th> * <td class="colLast" style="width:13%; text-align:center; color:#0c0">Yes <a href="#path-fn-4">[4]</a></td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * </tr> * <tr class="altColor"> * <th scope="row" class="colLast" style="width:22%"> * {@link #fill() fill()} * </th> * <td class="colLast" style="width:13%; text-align:center; color:#0c0">Yes <a href="#path-fn-4">[4]</a></td> * <td class="colLast" style="width:13%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * </tr> * <tr class="rowColor"> * <th scope="row" class="colLast" style="width:22%"> * {@link #stroke() stroke()} * </th> * <td class="colLast" style="width:13%; text-align:center; color:#0c0">Yes <a href="#path-fn-4">[4]</a></td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#0c0">Yes <a href="#path-fn-5">[5]</a></td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * </tr> * <tr class="altColor"> * <th scope="row" class="colLast" style="width:22%"> * {@link #clip() clip()} * </th> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * </tr> * <tr><th scope="row" colspan="6"> * <a id="path-fn-4">[4]</a> Transform applied only during path construction<br> * <a id="path-fn-5">[5]</a> Fill Rule only used for fill() and clip() * </th></tr> * <tr><th scope="row" colspan="1">Image Rendering</th></tr> * <tr class="rowColor"> * <th scope="row" class="colLast" style="width:22%"> * {@link #drawImage(javafx.scene.image.Image, double, double) drawImage(all forms)} * </th> * <td class="colLast" style="width:13%; text-align:center; color:#0c0">Yes</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#0c0">Yes</td> * </tr> * <tr><th scope="row" colspan="1">Miscellaneous</th></tr> * <tr class="rowColor"> * <th scope="row" class="colLast" style="width:22%"> * {@link #applyEffect(javafx.scene.effect.Effect) applyEffect()}, * {@link #getPixelWriter() PixelWriter methods} * </th> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * <td class="colLast" style="width:13%; text-align:center; color:#c00">No</td> * </tr> * </table> * * <p>Example:</p> * * <pre> * import javafx.scene.*; * import javafx.scene.paint.*; * import javafx.scene.canvas.*; * * Group root = new Group(); * Scene s = new Scene(root, 300, 300, Color.BLACK); * * final Canvas canvas = new Canvas(250,250); * GraphicsContext gc = canvas.getGraphicsContext2D(); * * gc.setFill(Color.BLUE); * gc.fillRect(75,75,100,100); * * root.getChildren().add(canvas); * </pre> * * @see Canvas * @since JavaFX 2.2 */
public final class GraphicsContext { Canvas theCanvas; Path2D path; boolean pathDirty; State curState; LinkedList<State> stateStack; LinkedList<Path2D> clipStack; GraphicsContext(Canvas theCanvas) { this.theCanvas = theCanvas; this.path = new Path2D(); pathDirty = true; this.curState = new State(); this.stateStack = new LinkedList<State>(); this.clipStack = new LinkedList<Path2D>(); } static class State { double globalAlpha; BlendMode blendop; Affine2D transform; Paint fill; Paint stroke; double linewidth; StrokeLineCap linecap; StrokeLineJoin linejoin; double miterlimit; double dashes[]; double dashOffset; int numClipPaths; Font font; FontSmoothingType fontsmoothing; TextAlignment textalign; VPos textbaseline; Effect effect; FillRule fillRule; boolean imageSmoothing = true; State() { init(); } final void init() { set(1.0, BlendMode.SRC_OVER, new Affine2D(), Color.BLACK, Color.BLACK, 1.0, StrokeLineCap.SQUARE, StrokeLineJoin.MITER, 10.0, null, 0.0, 0, Font.getDefault(), FontSmoothingType.GRAY, TextAlignment.LEFT, VPos.BASELINE, null, FillRule.NON_ZERO, true); } State(State copy) { set(copy.globalAlpha, copy.blendop, new Affine2D(copy.transform), copy.fill, copy.stroke, copy.linewidth, copy.linecap, copy.linejoin, copy.miterlimit, copy.dashes, copy.dashOffset, copy.numClipPaths, copy.font, copy.fontsmoothing, copy.textalign, copy.textbaseline, copy.effect, copy.fillRule, copy.imageSmoothing); } final void set(double globalAlpha, BlendMode blendop, Affine2D transform, Paint fill, Paint stroke, double linewidth, StrokeLineCap linecap, StrokeLineJoin linejoin, double miterlimit, double dashes[], double dashOffset, int numClipPaths, Font font, FontSmoothingType smoothing, TextAlignment align, VPos baseline, Effect effect, FillRule fillRule, boolean imageSmoothing) { this.globalAlpha = globalAlpha; this.blendop = blendop; this.transform = transform; this.fill = fill; this.stroke = stroke; this.linewidth = linewidth; this.linecap = linecap; this.linejoin = linejoin; this.miterlimit = miterlimit; this.dashes = dashes; this.dashOffset = dashOffset; this.numClipPaths = numClipPaths; this.font = font; this.fontsmoothing = smoothing; this.textalign = align; this.textbaseline = baseline; this.effect = effect; this.fillRule = fillRule; this.imageSmoothing = imageSmoothing; } State copy() { return new State(this); } void restore(GraphicsContext ctx) { ctx.setGlobalAlpha(globalAlpha); ctx.setGlobalBlendMode(blendop); ctx.setTransform(transform.getMxx(), transform.getMyx(), transform.getMxy(), transform.getMyy(), transform.getMxt(), transform.getMyt()); ctx.setFill(fill); ctx.setStroke(stroke); ctx.setLineWidth(linewidth); ctx.setLineCap(linecap); ctx.setLineJoin(linejoin); ctx.setMiterLimit(miterlimit); ctx.setLineDashes(dashes); ctx.setLineDashOffset(dashOffset); GrowableDataBuffer buf = ctx.getBuffer(); while (ctx.curState.numClipPaths > numClipPaths) { ctx.curState.numClipPaths--; ctx.clipStack.removeLast(); buf.putByte(NGCanvas.POP_CLIP); } ctx.setFillRule(fillRule); ctx.setFont(font); ctx.setFontSmoothingType(fontsmoothing); ctx.setTextAlign(textalign); ctx.setTextBaseline(textbaseline); ctx.setEffect(effect); ctx.setImageSmoothing(imageSmoothing); } } private GrowableDataBuffer getBuffer() { return theCanvas.getBuffer(); } private float coords[] = new float[6]; private static final byte pgtype[] = { NGCanvas.MOVETO, NGCanvas.LINETO, NGCanvas.QUADTO, NGCanvas.CUBICTO, NGCanvas.CLOSEPATH, }; private static final int numsegs[] = { 2, 2, 4, 6, 0, }; private void markPathDirty() { pathDirty = true; } private void writePath(byte command) { updateTransform(); GrowableDataBuffer buf = getBuffer(); if (pathDirty) { buf.putByte(NGCanvas.PATHSTART); PathIterator pi = path.getPathIterator(null); while (!pi.isDone()) { int pitype = pi.currentSegment(coords); buf.putByte(pgtype[pitype]); for (int i = 0; i < numsegs[pitype]; i++) { buf.putFloat(coords[i]); } pi.next(); } buf.putByte(NGCanvas.PATHEND); pathDirty = false; } buf.putByte(command); } private void writePaint(Paint p, byte command) { GrowableDataBuffer buf = getBuffer(); buf.putByte(command); buf.putObject(Toolkit.getPaintAccessor().getPlatformPaint(p)); } private void writeArcType(ArcType closure) { byte type; switch (closure) { case OPEN: type = NGCanvas.ARC_OPEN; break; case CHORD: type = NGCanvas.ARC_CHORD; break; case ROUND: type = NGCanvas.ARC_PIE; break; default: return; // ignored for consistency with other attributes } writeParam(type, NGCanvas.ARC_TYPE); } private void writeRectParams(GrowableDataBuffer buf, double x, double y, double w, double h, byte command) { buf.putByte(command); buf.putFloat((float) x); buf.putFloat((float) y); buf.putFloat((float) w); buf.putFloat((float) h); } private void writeOp4(double x, double y, double w, double h, byte command) { updateTransform(); writeRectParams(getBuffer(), x, y, w, h, command); } private void writeOp6(double x, double y, double w, double h, double v1, double v2, byte command) { updateTransform(); GrowableDataBuffer buf = getBuffer(); buf.putByte(command); buf.putFloat((float) x); buf.putFloat((float) y); buf.putFloat((float) w); buf.putFloat((float) h); buf.putFloat((float) v1); buf.putFloat((float) v2); } private float polybuf[] = new float[512]; private void flushPolyBuf(GrowableDataBuffer buf, float polybuf[], int n, byte command) { curState.transform.transform(polybuf, 0, polybuf, 0, n/2); for (int i = 0; i < n; i += 2) { buf.putByte(command); buf.putFloat(polybuf[i]); buf.putFloat(polybuf[i+1]); command = NGCanvas.LINETO; } } 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; byte polycmd = NGCanvas.MOVETO; for (int i = 0; i < nPoints; i++) { if (pos >= polybuf.length) { flushPolyBuf(buf, polybuf, pos, polycmd); pos = 0; polycmd = NGCanvas.LINETO; } polybuf[pos++] = (float) xPoints[i]; polybuf[pos++] = (float) yPoints[i]; } flushPolyBuf(buf, polybuf, pos, polycmd); if (close) { buf.putByte(NGCanvas.CLOSEPATH); } buf.putByte(NGCanvas.PATHEND); // Transform needs to be updated for rendering attributes even though // we have already transformed the points as we sent them. updateTransform(); buf.putByte(command); // Now that we have changed the PG layer path, we need to mark our path dirty. markPathDirty(); } private void writeImage(Image img, double dx, double dy, double dw, double dh) { if (img == null || img.getProgress() < 1.0) return; Object platformImg = Toolkit.getImageAccessor().getPlatformImage(img); if (platformImg == null) return; updateTransform(); GrowableDataBuffer buf = getBuffer(); writeRectParams(buf, dx, dy, dw, dh, NGCanvas.DRAW_IMAGE); buf.putObject(platformImg); } private void writeImage(Image img, double dx, double dy, double dw, double dh, double sx, double sy, double sw, double sh) { if (img == null || img.getProgress() < 1.0) return; Object platformImg = Toolkit.getImageAccessor().getPlatformImage(img); if (platformImg == null) return; updateTransform(); GrowableDataBuffer buf = getBuffer(); writeRectParams(buf, dx, dy, dw, dh, NGCanvas.DRAW_SUBIMAGE); buf.putFloat((float) sx); buf.putFloat((float) sy); buf.putFloat((float) sw); buf.putFloat((float) sh); buf.putObject(platformImg); } private void writeText(String text, double x, double y, double maxWidth, byte command) { if (text == null) return; updateTransform(); GrowableDataBuffer buf = getBuffer(); buf.putByte(command); buf.putFloat((float) x); buf.putFloat((float) y); buf.putFloat((float) maxWidth); buf.putBoolean(theCanvas.getEffectiveNodeOrientation() == NodeOrientation.RIGHT_TO_LEFT); buf.putObject(text); } void writeParam(double v, byte command) { GrowableDataBuffer buf = getBuffer(); buf.putByte(command); buf.putFloat((float) v); } private void writeParam(byte v, byte command) { GrowableDataBuffer buf = getBuffer(); buf.putByte(command); buf.putByte(v); } private boolean txdirty; private void updateTransform() { if (txdirty) { txdirty = false; GrowableDataBuffer buf = getBuffer(); buf.putByte(NGCanvas.TRANSFORM); buf.putDouble(curState.transform.getMxx()); buf.putDouble(curState.transform.getMxy()); buf.putDouble(curState.transform.getMxt()); buf.putDouble(curState.transform.getMyx()); buf.putDouble(curState.transform.getMyy()); buf.putDouble(curState.transform.getMyt()); } } void updateDimensions() { GrowableDataBuffer buf = getBuffer(); buf.putByte(NGCanvas.SET_DIMS); buf.putFloat((float) theCanvas.getWidth()); buf.putFloat((float) theCanvas.getHeight()); } private void reset() { GrowableDataBuffer buf = getBuffer(); // Only reset if we have a significant amount of data to omit, // this prevents a common occurrence of "setFill(bg); fillRect();" // at the start of a session from invoking a reset. // But, do a reset anyway if the rendering layer has been falling // behind because that lets the synchronization step throw out the // older buffers that have been backing up. if (buf.writeValuePosition() > Canvas.DEFAULT_VAL_BUF_SIZE || theCanvas.isRendererFallingBehind()) { buf.reset(); buf.putByte(NGCanvas.RESET); updateDimensions(); txdirty = true; pathDirty = true; State s = this.curState; int numClipPaths = this.curState.numClipPaths; this.curState = new State(); for (int i = 0; i < numClipPaths; i++) { Path2D clip = clipStack.get(i); buf.putByte(NGCanvas.PUSH_CLIP); buf.putObject(clip); } this.curState.numClipPaths = numClipPaths; s.restore(this); } } private void resetIfCovers(Paint p, double x, double y, double w, double h) { Affine2D tx = this.curState.transform; if (tx.isTranslateOrIdentity()) { x += tx.getMxt(); y += tx.getMyt(); if (x > 0 || y > 0 || (x+w) < theCanvas.getWidth() || (y+h) < theCanvas.getHeight()) { return; } } else { // quad test for coverage...? return; } if (p != null) { if (this.curState.blendop != BlendMode.SRC_OVER) return; if (!p.isOpaque() || this.curState.globalAlpha < 1.0) return; } if (this.curState.numClipPaths > 0) return; if (this.curState.effect != null) return; reset(); }
Gets the Canvas that the GraphicsContext is issuing draw commands to. There is only ever one Canvas for a GraphicsContext.
Returns:Canvas the canvas that this GraphicsContext is issuing draw commands to.
/** * Gets the {@code Canvas} that the {@code GraphicsContext} is issuing draw * commands to. There is only ever one {@code Canvas} for a * {@code GraphicsContext}. * * @return Canvas the canvas that this {@code GraphicsContext} is issuing draw * commands to. */
public Canvas getCanvas() { return theCanvas; }
Saves the following attributes onto a stack.
  • Global Alpha
  • Global Blend Operation
  • Transform
  • Fill Paint
  • Stroke Paint
  • Line Width
  • Line Cap
  • Line Join
  • Miter Limit
  • Clip
  • Font
  • Text Align
  • Text Baseline
  • Effect
  • Fill Rule
This method does NOT alter the current state in any way. Also, note that the current path is not saved.
/** * Saves the following attributes onto a stack. * <ul> * <li>Global Alpha</li> * <li>Global Blend Operation</li> * <li>Transform</li> * <li>Fill Paint</li> * <li>Stroke Paint</li> * <li>Line Width</li> * <li>Line Cap</li> * <li>Line Join</li> * <li>Miter Limit</li> * <li>Clip</li> * <li>Font</li> * <li>Text Align</li> * <li>Text Baseline</li> * <li>Effect</li> * <li>Fill Rule</li> * </ul> * This method does NOT alter the current state in any way. Also, note that * the current path is not saved. */
public void save() { stateStack.push(curState.copy()); }
Pops the state off of the stack, setting the following attributes to their value at the time when that state was pushed onto the stack. If the stack is empty then nothing is changed.
  • Global Alpha
  • Global Blend Operation
  • Transform
  • Fill Paint
  • Stroke Paint
  • Line Width
  • Line Cap
  • Line Join
  • Miter Limit
  • Clip
  • Font
  • Text Align
  • Text Baseline
  • Effect
  • Fill Rule
Note that the current path is not restored.
/** * Pops the state off of the stack, setting the following attributes to their * value at the time when that state was pushed onto the stack. If the stack * is empty then nothing is changed. * * <ul> * <li>Global Alpha</li> * <li>Global Blend Operation</li> * <li>Transform</li> * <li>Fill Paint</li> * <li>Stroke Paint</li> * <li>Line Width</li> * <li>Line Cap</li> * <li>Line Join</li> * <li>Miter Limit</li> * <li>Clip</li> * <li>Font</li> * <li>Text Align</li> * <li>Text Baseline</li> * <li>Effect</li> * <li>Fill Rule</li> * </ul> * Note that the current path is not restored. */
public void restore() { if (!stateStack.isEmpty()) { State savedState = stateStack.pop(); savedState.restore(this); txdirty = true; } }
Translates the current transform by x, y.
Params:
  • x – value to translate along the x axis.
  • y – value to translate along the y axis.
/** * Translates the current transform by x, y. * @param x value to translate along the x axis. * @param y value to translate along the y axis. */
public void translate(double x, double y) { curState.transform.translate(x, y); txdirty = true; }
Scales the current transform by x, y.
Params:
  • x – value to scale in the x axis.
  • y – value to scale in the y axis.
/** * Scales the current transform by x, y. * @param x value to scale in the x axis. * @param y value to scale in the y axis. */
public void scale(double x, double y) { curState.transform.scale(x, y); txdirty = true; }
Rotates the current transform in degrees.
Params:
  • degrees – value in degrees to rotate the current transform.
/** * Rotates the current transform in degrees. * @param degrees value in degrees to rotate the current transform. */
public void rotate(double degrees) { curState.transform.rotate(Math.toRadians(degrees)); txdirty = true; }
Concatenates the input with the current transform.
Params:
  • mxx – - the X coordinate scaling element of the 3x4 matrix
  • myx – - the Y coordinate shearing element of the 3x4 matrix
  • mxy – - the X coordinate shearing element of the 3x4 matrix
  • myy – - the Y coordinate scaling element of the 3x4 matrix
  • mxt – - the X coordinate translation element of the 3x4 matrix
  • myt – - the Y coordinate translation element of the 3x4 matrix
/** * Concatenates the input with the current transform. * * @param mxx - the X coordinate scaling element of the 3x4 matrix * @param myx - the Y coordinate shearing element of the 3x4 matrix * @param mxy - the X coordinate shearing element of the 3x4 matrix * @param myy - the Y coordinate scaling element of the 3x4 matrix * @param mxt - the X coordinate translation element of the 3x4 matrix * @param myt - the Y coordinate translation element of the 3x4 matrix */
public void transform(double mxx, double myx, double mxy, double myy, double mxt, double myt) { curState.transform.concatenate(mxx, mxy, mxt, myx, myy, myt); txdirty = true; }
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. A null value is treated as identity.
Params:
  • xform – The affine to be concatenated with the current transform or null.
/** * 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. A {@code null} value is treated as identity. * * @param xform The affine to be concatenated with the current transform or null. */
public void transform(Affine xform) { if (xform == null) return; curState.transform.concatenate(xform.getMxx(), xform.getMxy(), xform.getTx(), xform.getMyx(), xform.getMyy(), xform.getTy()); txdirty = true; }
Sets the current transform.
Params:
  • mxx – - the X coordinate scaling element of the 3x4 matrix
  • myx – - the Y coordinate shearing element of the 3x4 matrix
  • mxy – - the X coordinate shearing element of the 3x4 matrix
  • myy – - the Y coordinate scaling element of the 3x4 matrix
  • mxt – - the X coordinate translation element of the 3x4 matrix
  • myt – - the Y coordinate translation element of the 3x4 matrix
/** * Sets the current transform. * @param mxx - the X coordinate scaling element of the 3x4 matrix * @param myx - the Y coordinate shearing element of the 3x4 matrix * @param mxy - the X coordinate shearing element of the 3x4 matrix * @param myy - the Y coordinate scaling element of the 3x4 matrix * @param mxt - the X coordinate translation element of the 3x4 matrix * @param myt - the Y coordinate translation element of the 3x4 matrix */
public void setTransform(double mxx, double myx, double mxy, double myy, double mxt, double myt) { curState.transform.setTransform(mxx, myx, mxy, myy, mxt, myt); txdirty = true; }
Sets 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.
Params:
  • xform – The affine to be copied and used as the current transform.
/** * Sets 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. * * @param xform The affine to be copied and used as the current transform. */
public void setTransform(Affine xform) { curState.transform.setTransform(xform.getMxx(), xform.getMyx(), xform.getMxy(), xform.getMyy(), xform.getTx(), xform.getTy()); txdirty = true; }
Copies the current transform into the supplied object, creating a new Affine object if it is null, and returns the object containing the copy.
Params:
  • xform – A transform object that will be used to hold the result. If xform is non null, then this method will copy the current transform into that object. If xform is null a new transform object will be constructed. In either case, the return value is a copy of the current transform.
Returns:A copy of the current transform.
/** * Copies the current transform into the supplied object, creating * a new {@link Affine} object if it is null, and returns the object * containing the copy. * * @param xform A transform object that will be used to hold the result. * If xform is non null, then this method will copy the current transform * into that object. If xform is null a new transform object will be * constructed. In either case, the return value is a copy of the current * transform. * * @return A copy of the current transform. */
public Affine getTransform(Affine xform) { if (xform == null) { xform = new Affine(); } xform.setMxx(curState.transform.getMxx()); xform.setMxy(curState.transform.getMxy()); xform.setMxz(0); xform.setTx(curState.transform.getMxt()); xform.setMyx(curState.transform.getMyx()); xform.setMyy(curState.transform.getMyy()); xform.setMyz(0); xform.setTy(curState.transform.getMyt()); xform.setMzx(0); xform.setMzy(0); xform.setMzz(1); xform.setTz(0); return xform; }
Returns a copy of the current transform.
Returns:a copy of the transform of the current state.
/** * Returns a copy of the current transform. * * @return a copy of the transform of the current state. */
public Affine getTransform() { return getTransform(null); }
Sets the global alpha of the current state. The default value is 1.0. Any valid double can be set, but only values in the range [0.0, 1.0] are valid and the nearest value in that range will be used for rendering. The global alpha is a common attribute used for nearly all rendering methods as specified in the Rendering Attributes Table.
Params:
  • alpha – the new alpha value, clamped to [0.0, 1.0] during actual use.
/** * Sets the global alpha of the current state. * The default value is {@code 1.0}. * Any valid double can be set, but only values in the range * {@code [0.0, 1.0]} are valid and the nearest value in that * range will be used for rendering. * The global alpha is a <a href="#comm-attr">common attribute</a> * used for nearly all rendering methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * * @param alpha the new alpha value, clamped to {@code [0.0, 1.0]} * during actual use. */
public void setGlobalAlpha(double alpha) { if (curState.globalAlpha != alpha) { curState.globalAlpha = alpha; alpha = (alpha > 1.0) ? 1.0 : (alpha < 0.0) ? 0.0 : alpha; writeParam(alpha, NGCanvas.GLOBAL_ALPHA); } }
Gets the current global alpha. The default value is 1.0. The global alpha is a common attribute used for nearly all rendering methods as specified in the Rendering Attributes Table.
Returns:the current global alpha.
/** * Gets the current global alpha. * The default value is {@code 1.0}. * The global alpha is a <a href="#comm-attr">common attribute</a> * used for nearly all rendering methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * * @return the current global alpha. */
public double getGlobalAlpha() { return curState.globalAlpha; }
Sets the global blend mode. The default value is SRC_OVER. A null value will be ignored and the current value will remain unchanged. The blend mode is a common attribute used for nearly all rendering methods as specified in the Rendering Attributes Table.
Params:
  • op – the BlendMode that will be set or null.
/** * Sets the global blend mode. * The default value is {@link BlendMode#SRC_OVER SRC_OVER}. * A {@code null} value will be ignored and the current value will remain unchanged. * The blend mode is a <a href="#comm-attr">common attribute</a> * used for nearly all rendering methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * * @param op the {@code BlendMode} that will be set or null. */
public void setGlobalBlendMode(BlendMode op) { if (op != null && op != curState.blendop) { GrowableDataBuffer buf = getBuffer(); curState.blendop = op; buf.putByte(NGCanvas.COMP_MODE); buf.putObject(EffectHelper.getToolkitBlendMode(op)); } }
Gets the global blend mode. The default value is SRC_OVER. The blend mode is a common attribute used for nearly all rendering methods as specified in the Rendering Attributes Table.
Returns:the global BlendMode of the current state.
/** * Gets the global blend mode. * The default value is {@link BlendMode#SRC_OVER SRC_OVER}. * The blend mode is a <a href="#comm-attr">common attribute</a> * used for nearly all rendering methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * * @return the global {@code BlendMode} of the current state. */
public BlendMode getGlobalBlendMode() { return curState.blendop; }
Sets the current fill paint attribute. The default value is BLACK. The fill paint is a fill attribute used for any of the fill methods as specified in the Rendering Attributes Table. A null value will be ignored and the current value will remain unchanged.
Params:
  • p – The Paint to be used as the fill Paint or null.
/** * Sets the current fill paint attribute. * The default value is {@link Color#BLACK BLACK}. * The fill paint is a <a href="#fill-attr">fill attribute</a> * used for any of the fill methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * 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} or null. */
public void setFill(Paint p) { if (p != null && curState.fill != p) { curState.fill = p; writePaint(p, NGCanvas.FILL_PAINT); } }
Gets the current fill paint attribute. The default value is BLACK. The fill paint is a fill attribute used for any of the fill methods as specified in the Rendering Attributes Table.
Returns:p The Paint to be used as the fill Paint.
/** * Gets the current fill paint attribute. * The default value is {@link Color#BLACK BLACK}. * The fill paint is a <a href="#fill-attr">fill attribute</a> * used for any of the fill methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * * @return p The {@code Paint} to be used as the fill {@code Paint}. */
public Paint getFill() { return curState.fill; }
Sets the current stroke paint attribute. The default value is BLACK. The stroke paint is a stroke attribute used for any of the stroke methods as specified in the Rendering Attributes Table. A null value will be ignored and the current value will remain unchanged.
Params:
  • p – The Paint to be used as the stroke Paint or null.
/** * Sets the current stroke paint attribute. * The default value is {@link Color#BLACK BLACK}. * The stroke paint is a <a href="#strk-attr">stroke attribute</a> * used for any of the stroke methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * 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 or null. */
public void setStroke(Paint p) { if (p != null && curState.stroke != p) { curState.stroke = p; writePaint(p, NGCanvas.STROKE_PAINT); } }
Gets the current stroke. The default value is BLACK. The stroke paint is a stroke attribute used for any of the stroke methods as specified in the Rendering Attributes Table.
Returns:the Paint to be used as the stroke Paint.
/** * Gets the current stroke. * The default value is {@link Color#BLACK BLACK}. * The stroke paint is a <a href="#strk-attr">stroke attribute</a> * used for any of the stroke methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * * @return the {@code Paint} to be used as the stroke {@code Paint}. */
public Paint getStroke() { return curState.stroke; }
Sets the current line width. The default value is 1.0. The line width is a stroke attribute used for any of the stroke methods as specified in the Rendering Attributes Table. An infinite or non-positive value outside of the range (0, +inf) will be ignored and the current value will remain unchanged.
Params:
  • lw – value in the range {0-positive infinity}, with any other value being ignored and leaving the value unchanged.
/** * Sets the current line width. * The default value is {@code 1.0}. * The line width is a <a href="#strk-attr">stroke attribute</a> * used for any of the stroke methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * An infinite or non-positive value outside of the range {@code (0, +inf)} * will be ignored and the current value will remain unchanged. * * @param lw value in the range {0-positive infinity}, with any other value * being ignored and leaving the value unchanged. */
public void setLineWidth(double lw) { // Per W3C spec: On setting, zero, negative, infinite, and NaN // values must be ignored, leaving the value unchanged if (lw > 0 && lw < Double.POSITIVE_INFINITY) { if (curState.linewidth != lw) { curState.linewidth = lw; writeParam(lw, NGCanvas.LINE_WIDTH); } } }
Gets the current line width. The default value is 1.0. The line width is a stroke attribute used for any of the stroke methods as specified in the Rendering Attributes Table.
Returns:value between 0 and infinity.
/** * Gets the current line width. * The default value is {@code 1.0}. * The line width is a <a href="#strk-attr">stroke attribute</a> * used for any of the stroke methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * * @return value between 0 and infinity. */
public double getLineWidth() { return curState.linewidth; }
Sets the current stroke line cap. The default value is SQUARE. The line cap is a stroke attribute used for any of the stroke methods as specified in the Rendering Attributes Table. A null value will be ignored and the current value will remain unchanged.
Params:
  • cap – StrokeLineCap with a value of Butt, Round, or Square or null.
/** * Sets the current stroke line cap. * The default value is {@link StrokeLineCap#SQUARE SQUARE}. * The line cap is a <a href="#strk-attr">stroke attribute</a> * used for any of the stroke methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * 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 or null. */
public void setLineCap(StrokeLineCap cap) { if (cap != null && curState.linecap != cap) { byte v; switch (cap) { case BUTT: v = NGCanvas.CAP_BUTT; break; case ROUND: v = NGCanvas.CAP_ROUND; break; case SQUARE: v = NGCanvas.CAP_SQUARE; break; default: return; } curState.linecap = cap; writeParam(v, NGCanvas.LINE_CAP); } }
Gets the current stroke line cap. The default value is SQUARE. The line cap is a stroke attribute used for any of the stroke methods as specified in the Rendering Attributes Table.
Returns:StrokeLineCap with a value of Butt, Round, or Square.
/** * Gets the current stroke line cap. * The default value is {@link StrokeLineCap#SQUARE SQUARE}. * The line cap is a <a href="#strk-attr">stroke attribute</a> * used for any of the stroke methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * * @return {@code StrokeLineCap} with a value of Butt, Round, or Square. */
public StrokeLineCap getLineCap() { return curState.linecap; }
Sets the current stroke line join. The default value is StrokeLineJoin.MITER. The line join is a stroke attribute used for any of the stroke methods as specified in the Rendering Attributes Table. A null value will be ignored and the current value will remain unchanged.
Params:
  • join – StrokeLineJoin with a value of Miter, Bevel, or Round or null.
/** * Sets the current stroke line join. * The default value is {@link StrokeLineJoin#MITER}. * The line join is a <a href="#strk-attr">stroke attribute</a> * used for any of the stroke methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * 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 or null. */
public void setLineJoin(StrokeLineJoin join) { if (join != null && curState.linejoin != join) { byte v; switch (join) { case MITER: v = NGCanvas.JOIN_MITER; break; case BEVEL: v = NGCanvas.JOIN_BEVEL; break; case ROUND: v = NGCanvas.JOIN_ROUND; break; default: return; } curState.linejoin = join; writeParam(v, NGCanvas.LINE_JOIN); } }
Gets the current stroke line join. The default value is StrokeLineJoin.MITER. The line join is a stroke attribute used for any of the stroke methods as specified in the Rendering Attributes Table.
Returns:StrokeLineJoin with a value of Miter, Bevel, or Round.
/** * Gets the current stroke line join. * The default value is {@link StrokeLineJoin#MITER}. * The line join is a <a href="#strk-attr">stroke attribute</a> * used for any of the stroke methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * * @return {@code StrokeLineJoin} with a value of Miter, Bevel, or Round. */
public StrokeLineJoin getLineJoin() { return curState.linejoin; }
Sets the current miter limit. The default value is 10.0. The miter limit is a stroke attribute used for any of the stroke methods as specified in the Rendering Attributes Table. An infinite or non-positive value outside of the range (0, +inf) will be ignored and the current value will remain unchanged.
Params:
  • ml – miter limit value between 0 and positive infinity with any other value being ignored and leaving the value unchanged.
/** * Sets the current miter limit. * The default value is {@code 10.0}. * The miter limit is a <a href="#strk-attr">stroke attribute</a> * used for any of the stroke methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * An infinite or non-positive value outside of the range {@code (0, +inf)} * will be ignored and the current value will remain unchanged. * * @param ml miter limit value between 0 and positive infinity with * any other value being ignored and leaving the value unchanged. */
public void setMiterLimit(double ml) { // Per W3C spec: On setting, zero, negative, infinite, and NaN // values must be ignored, leaving the value unchanged if (ml > 0.0 && ml < Double.POSITIVE_INFINITY) { if (curState.miterlimit != ml) { curState.miterlimit = ml; writeParam(ml, NGCanvas.MITER_LIMIT); } } }
Gets the current miter limit. The default value is 10.0. The miter limit is a stroke attribute used for any of the stroke methods as specified in the Rendering Attributes Table.
Returns:the miter limit value in the range 0.0-positive infinity
/** * Gets the current miter limit. * The default value is {@code 10.0}. * The miter limit is a <a href="#strk-attr">stroke attribute</a> * used for any of the stroke methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * * @return the miter limit value in the range {@code 0.0-positive infinity} */
public double getMiterLimit() { return curState.miterlimit; }
Sets the current stroke line dash pattern to a normalized copy of the argument. The default value is null. The line dash array is a stroke attribute used for any of the stroke methods as specified in the Rendering Attributes Table. If the array is null or empty or contains all 0 elements then dashing will be disabled and the current dash array will be set to null. If any of the elements of the array are a negative, infinite, or NaN value outside the range [0, +inf) then the entire array will be ignored and the current dash array will remain unchanged. If the array is an odd length then it will be treated as if it were two copies of the array appended to each other.
Params:
  • dashes – the array of finite non-negative dash lengths
Since:JavaFX 8u40
/** * Sets the current stroke line dash pattern to a normalized copy of * the argument. * The default value is {@code null}. * The line dash array is a <a href="#strk-attr">stroke attribute</a> * used for any of the stroke methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * If the array is {@code null} or empty or contains all {@code 0} elements * then dashing will be disabled and the current dash array will be set * to {@code null}. * If any of the elements of the array are a negative, infinite, or NaN * value outside the range {@code [0, +inf)} then the entire array will * be ignored and the current dash array will remain unchanged. * If the array is an odd length then it will be treated as if it * were two copies of the array appended to each other. * * @param dashes the array of finite non-negative dash lengths * @since JavaFX 8u40 */
public void setLineDashes(double... dashes) { if (dashes == null || dashes.length == 0) { if (curState.dashes == null) { return; } curState.dashes = null; } else { boolean allZeros = true; for (int i = 0; i < dashes.length; i++) { double d = dashes[i]; if (d >= 0.0 && d < Double.POSITIVE_INFINITY) { // Non-NaN, finite, non-negative // Test cannot be inverted or it will not implicitly test for NaN if (d > 0) { allZeros = false; } } else { return; } } if (allZeros) { if (curState.dashes == null) { return; } curState.dashes = null; } else { int dashlen = dashes.length; if ((dashlen & 1) == 0) { curState.dashes = Arrays.copyOf(dashes, dashlen); } else { curState.dashes = Arrays.copyOf(dashes, dashlen * 2); System.arraycopy(dashes, 0, curState.dashes, dashlen, dashlen); } } } GrowableDataBuffer buf = getBuffer(); buf.putByte(NGCanvas.DASH_ARRAY); buf.putObject(curState.dashes); }
Gets a copy of the current line dash array. The default value is null. The array may be normalized by the validation tests in the setLineDashes(double...) method. The line dash array is a stroke attribute used for any of the stroke methods as specified in the Rendering Attributes Table.
Returns:a copy of the current line dash array.
Since:JavaFX 8u40
/** * Gets a copy of the current line dash array. * The default value is {@code null}. * The array may be normalized by the validation tests in the * {@link #setLineDashes(double...)} method. * The line dash array is a <a href="#strk-attr">stroke attribute</a> * used for any of the stroke methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * * @return a copy of the current line dash array. * @since JavaFX 8u40 */
public double[] getLineDashes() { if (curState.dashes == null) { return null; } return Arrays.copyOf(curState.dashes, curState.dashes.length); }
Sets the line dash offset. The default value is 0.0. The line dash offset is a stroke attribute used for any of the stroke methods as specified in the Rendering Attributes Table. An infinite or NaN value outside of the range (-inf, +inf) will be ignored and the current value will remain unchanged.
Params:
  • dashOffset – the line dash offset in the range (-inf, +inf)
Since:JavaFX 8u40
/** * Sets the line dash offset. * The default value is {@code 0.0}. * The line dash offset is a <a href="#strk-attr">stroke attribute</a> * used for any of the stroke methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * An infinite or NaN value outside of the range {@code (-inf, +inf)} * will be ignored and the current value will remain unchanged. * * @param dashOffset the line dash offset in the range {@code (-inf, +inf)} * @since JavaFX 8u40 */
public void setLineDashOffset(double dashOffset) { // Per W3C spec: On setting, infinite, and NaN // values must be ignored, leaving the value unchanged if (dashOffset > Double.NEGATIVE_INFINITY && dashOffset < Double.POSITIVE_INFINITY) { curState.dashOffset = dashOffset; writeParam(dashOffset, NGCanvas.DASH_OFFSET); } }
Gets the current line dash offset. The default value is 0.0. The line dash offset is a stroke attribute used for any of the stroke methods as specified in the Rendering Attributes Table.
Returns:the line dash offset in the range (-inf, +inf)
Since:JavaFX 8u40
/** * Gets the current line dash offset. * The default value is {@code 0.0}. * The line dash offset is a <a href="#strk-attr">stroke attribute</a> * used for any of the stroke methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * * @return the line dash offset in the range {@code (-inf, +inf)} * @since JavaFX 8u40 */
public double getLineDashOffset() { return curState.dashOffset; }
Sets the current Font. The default value is specified by Font.getDefault(). The font is a text attribute used for any of the text methods as specified in the Rendering Attributes Table. A null value will be ignored and the current value will remain unchanged.
Params:
  • f – the Font or null.
/** * Sets the current Font. * The default value is specified by {@link Font#getDefault()}. * The font is a <a href="#text-attr">text attribute</a> * used for any of the text methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * A {@code null} value will be ignored and the current value will remain unchanged. * * @param f the Font or null. */
public void setFont(Font f) { if (f != null && curState.font != f) { curState.font = f; GrowableDataBuffer buf = getBuffer(); buf.putByte(NGCanvas.FONT); buf.putObject(FontHelper.getNativeFont(f)); } }
Gets the current Font. The default value is specified by Font.getDefault(). The font is a text attribute used for any of the text methods as specified in the Rendering Attributes Table.
Returns:the Font
/** * Gets the current Font. * The default value is specified by {@link Font#getDefault()}. * The font is a <a href="#text-attr">text attribute</a> * used for any of the text methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * * @return the Font */
public Font getFont() { return curState.font; }
Sets the current Font Smoothing Type. The default value is GRAY. The font smoothing type is a text attribute used for any of the text methods as specified in the Rendering Attributes Table. A null value will be ignored and the current value will remain unchanged.

Note that the FontSmoothingType value of LCD is only supported over an opaque background. LCD text will generally appear as GRAY text over transparent or partially transparent pixels, and in some implementations it may not be supported at all on a Canvas because the required support does not exist for surfaces which contain an alpha channel as all Canvas objects do.

Params:
Since:JavaFX 8u40
/** * Sets the current Font Smoothing Type. * The default value is {@link FontSmoothingType#GRAY GRAY}. * The font smoothing type is a <a href="#text-attr">text attribute</a> * used for any of the text methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * A {@code null} value will be ignored and the current value will remain unchanged. * <p> * <b>Note</b> that the {@code FontSmoothingType} value of * {@link FontSmoothingType#LCD LCD} is only supported over an opaque * background. {@code LCD} text will generally appear as {@code GRAY} * text over transparent or partially transparent pixels, and in some * implementations it may not be supported at all on a {@link Canvas} * because the required support does not exist for surfaces which contain * an alpha channel as all {@code Canvas} objects do. * * @param fontsmoothing the {@link FontSmoothingType} or null * @since JavaFX 8u40 */
public void setFontSmoothingType(FontSmoothingType fontsmoothing) { if (fontsmoothing != null && fontsmoothing != curState.fontsmoothing) { curState.fontsmoothing = fontsmoothing; writeParam((byte) fontsmoothing.ordinal(), NGCanvas.FONT_SMOOTH); } }
Gets the current Font Smoothing Type. The default value is GRAY. The font smoothing type is a text attribute used for any of the text methods as specified in the Rendering Attributes Table.
Returns:the FontSmoothingType
Since:JavaFX 8u40
/** * Gets the current Font Smoothing Type. * The default value is {@link FontSmoothingType#GRAY GRAY}. * The font smoothing type is a <a href="#text-attr">text attribute</a> * used for any of the text methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * * @return the {@link FontSmoothingType} * @since JavaFX 8u40 */
public FontSmoothingType getFontSmoothingType() { return curState.fontsmoothing; }
Defines horizontal text alignment, relative to the text x origin. The default value is LEFT. The text alignment is a text attribute used for any of the text methods as specified in the Rendering Attributes Table.

Let horizontal bounds represent the logical width of a single line of text. Where each line of text has a separate horizontal bounds.

Then TextAlignment is specified as:

  • Left: the left edge of the horizontal bounds will be at x.
  • Center: the center, halfway between left and right edge, of the horizontal bounds will be at x.
  • Right: the right edge of the horizontal bounds will be at x.

Note: Canvas does not support line wrapping, therefore the text alignment Justify is identical to left aligned text.

A null value will be ignored and the current value will remain unchanged.

Params:
  • align – TextAlignment with values of Left, Center, Right or null.
/** * Defines horizontal text alignment, relative to the text {@code x} origin. * The default value is {@link TextAlignment#LEFT LEFT}. * The text alignment is a <a href="#text-attr">text attribute</a> * used for any of the text methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * <p> * Let horizontal bounds represent the logical width of a single line of * text. Where each line of text has a separate horizontal bounds. * <p> * Then TextAlignment is specified as: * <ul> * <li>Left: the left edge of the horizontal bounds will be at {@code x}. * <li>Center: the center, halfway between left and right edge, of the * horizontal bounds will be at {@code x}. * <li>Right: the right edge of the horizontal bounds will be at {@code x}. * </ul> * <p> * * 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 or null. */
public void setTextAlign(TextAlignment align) { if (align != null && curState.textalign != align) { byte a; switch (align) { case LEFT: a = NGCanvas.ALIGN_LEFT; break; case CENTER: a = NGCanvas.ALIGN_CENTER; break; case RIGHT: a = NGCanvas.ALIGN_RIGHT; break; case JUSTIFY: a = NGCanvas.ALIGN_JUSTIFY; break; default: return; } curState.textalign = align; writeParam(a, NGCanvas.TEXT_ALIGN); } }
Gets the current TextAlignment. The default value is LEFT. The text alignment is a text attribute used for any of the text methods as specified in the Rendering Attributes Table.
Returns:TextAlignment with values of Left, Center, Right, or Justify.
/** * Gets the current {@code TextAlignment}. * The default value is {@link TextAlignment#LEFT LEFT}. * The text alignment is a <a href="#text-attr">text attribute</a> * used for any of the text methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * * @return {@code TextAlignment} with values of Left, Center, Right, or * Justify. */
public TextAlignment getTextAlign() { return curState.textalign; }
Sets the current Text Baseline. The default value is BASELINE. The text baseline is a text attribute used for any of the text methods as specified in the Rendering Attributes Table. A null value will be ignored and the current value will remain unchanged.
Params:
  • baseline – VPos with values of Top, Center, Baseline, or Bottom or null.
/** * Sets the current Text Baseline. * The default value is {@link VPos#BASELINE BASELINE}. * The text baseline is a <a href="#text-attr">text attribute</a> * used for any of the text methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * 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 or null. */
public void setTextBaseline(VPos baseline) { if (baseline != null && curState.textbaseline != baseline) { byte b; switch (baseline) { case TOP: b = NGCanvas.BASE_TOP; break; case CENTER: b = NGCanvas.BASE_MIDDLE; break; case BASELINE: b = NGCanvas.BASE_ALPHABETIC; break; case BOTTOM: b = NGCanvas.BASE_BOTTOM; break; default: return; } curState.textbaseline = baseline; writeParam(b, NGCanvas.TEXT_BASELINE); } }
Gets the current Text Baseline. The default value is BASELINE. The text baseline is a text attribute used for any of the text methods as specified in the Rendering Attributes Table.
Returns:VPos with values of Top, Center, Baseline, or Bottom
/** * Gets the current Text Baseline. * The default value is {@link VPos#BASELINE BASELINE}. * The text baseline is a <a href="#text-attr">text attribute</a> * used for any of the text methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * * @return {@code VPos} with values of Top, Center, Baseline, or Bottom */
public VPos getTextBaseline() { return curState.textbaseline; }
Fills the given string of text at position x, y with the current fill paint attribute. A null text value will be ignored.

This method will be affected by any of the global common, fill, or text attributes as specified in the Rendering Attributes Table.

Params:
  • text – the string of text or null.
  • x – position on the x axis.
  • y – position on the y axis.
/** * Fills the given string of text at position x, y * with the current fill paint attribute. * A {@code null} text value will be ignored. * <p> * This method will be affected by any of the * <a href="#comm-attr">global common</a>, * <a href="#fill-attr">fill</a>, * or <a href="#text-attr">text</a> * attributes as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * </p> * * @param text the string of text or null. * @param x position on the x axis. * @param y position on the y axis. */
public void fillText(String text, double x, double y) { writeText(text, x, y, 0, NGCanvas.FILL_TEXT); }
Draws the given string of text at position x, y with the current stroke paint attribute. A null text value will be ignored.

This method will be affected by any of the global common, stroke, or text attributes as specified in the Rendering Attributes Table.

Params:
  • text – the string of text or null.
  • x – position on the x axis.
  • y – position on the y axis.
/** * Draws the given string of text at position x, y * with the current stroke paint attribute. * A {@code null} text value will be ignored. * <p> * This method will be affected by any of the * <a href="#comm-attr">global common</a>, * <a href="#strk-attr">stroke</a>, * or <a href="#text-attr">text</a> * attributes as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * </p> * * @param text the string of text or null. * @param x position on the x axis. * @param y position on the y axis. */
public void strokeText(String text, double x, double y) { writeText(text, x, y, 0, NGCanvas.STROKE_TEXT); }
Fills text and includes a maximum width of the string. If the width of the text extends past max width, then it will be sized to fit. A null text value will be ignored.

This method will be affected by any of the global common, fill, or text attributes as specified in the Rendering Attributes Table.

Params:
  • text – the string of text or null.
  • x – position on the x axis.
  • y – position on the y axis.
  • maxWidth – maximum width the text string can have.
/** * Fills text and includes a maximum width of the string. * 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. * <p> * This method will be affected by any of the * <a href="#comm-attr">global common</a>, * <a href="#fill-attr">fill</a>, * or <a href="#text-attr">text</a> * attributes as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * </p> * * @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. */
public void fillText(String text, double x, double y, double maxWidth) { if (maxWidth <= 0) return; writeText(text, x, y, maxWidth, NGCanvas.FILL_TEXT); }
Draws text with stroke paint and includes a maximum width of the string. If the width of the text extends past max width, then it will be sized to fit. A null text value will be ignored.

This method will be affected by any of the global common, stroke, or text attributes as specified in the Rendering Attributes Table.

Params:
  • text – the string of text or null.
  • x – position on the x axis.
  • y – position on the y axis.
  • maxWidth – maximum width the text string can have.
/** * Draws text with stroke paint and includes a maximum width of the string. * 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. * <p> * This method will be affected by any of the * <a href="#comm-attr">global common</a>, * <a href="#strk-attr">stroke</a>, * or <a href="#text-attr">text</a> * attributes as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * </p> * * @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. */
public void strokeText(String text, double x, double y, double maxWidth) { if (maxWidth <= 0) return; writeText(text, x, y, maxWidth, NGCanvas.STROKE_TEXT); }
Set the filling rule attribute for determining the interior of paths in fill or clip operations. The default value is FillRule.NON_ZERO. A null value will be ignored and the current value will remain unchanged. The fill rule is a path attribute used for any of the fill or clip path methods as specified in the Rendering Attributes Table.
Params:
  • fillRule – FillRule with a value of Even_odd or Non_zero or null.
/** * Set the filling rule attribute for determining the interior of paths * in fill or clip operations. * The default value is {@code FillRule.NON_ZERO}. * A {@code null} value will be ignored and the current value will remain unchanged. * The fill rule is a <a href="#path-attr">path attribute</a> * used for any of the fill or clip path methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * * @param fillRule {@code FillRule} with a value of Even_odd or Non_zero or null. */
public void setFillRule(FillRule fillRule) { if (fillRule != null && curState.fillRule != fillRule) { byte b; if (fillRule == FillRule.EVEN_ODD) { b = NGCanvas.FILL_RULE_EVEN_ODD; } else { b = NGCanvas.FILL_RULE_NON_ZERO; } curState.fillRule = fillRule; writeParam(b, NGCanvas.FILL_RULE); } }
Get the filling rule attribute for determining the interior of paths in fill and clip operations. The default value is FillRule.NON_ZERO. The fill rule is a path attribute used for any of the fill or clip path methods as specified in the Rendering Attributes Table.
Returns:current fill rule.
/** * Get the filling rule attribute for determining the interior of paths * in fill and clip operations. * The default value is {@code FillRule.NON_ZERO}. * The fill rule is a <a href="#path-attr">path attribute</a> * used for any of the fill or clip path methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * * @return current fill rule. */
public FillRule getFillRule() { return curState.fillRule; }
Sets the image smoothing state. Image smoothing is an Image attribute used to enable or disable image smoothing for drawImage(all forms) as specified in the Rendering Attributes Table.
If image smoothing is true, images will be scaled using a higher quality filtering when transforming or scaling the source image to fit in the destination rectangle.
If image smoothing is false, images will be scaled without filtering (or by using a lower quality filtering) when transforming or scaling the source image to fit in the destination rectangle.
Params:
  • imageSmoothing – true to enable or false to disable smoothing
@defaultValuetrue
Since:12
/** * Sets the image smoothing state. * Image smoothing is an <a href="#image-attr">Image attribute</a> * used to enable or disable image smoothing for * {@link #drawImage(javafx.scene.image.Image, double, double) drawImage(all forms)} * as specified in the <a href="#attr-ops-table">Rendering Attributes Table</a>.<br> * If image smoothing is {@code true}, images will be scaled using a higher * quality filtering when transforming or scaling the source image to fit * in the destination rectangle.<br> * If image smoothing is {@code false}, images will be scaled without filtering * (or by using a lower quality filtering) when transforming or scaling the * source image to fit in the destination rectangle. * * @defaultValue {@code true} * @param imageSmoothing {@code true} to enable or {@code false} to disable smoothing * @since 12 */
public void setImageSmoothing(boolean imageSmoothing) { if (curState.imageSmoothing != imageSmoothing) { curState.imageSmoothing = imageSmoothing; GrowableDataBuffer buf = getBuffer(); buf.putByte(NGCanvas.IMAGE_SMOOTH); buf.putBoolean(curState.imageSmoothing); } }
Gets the current image smoothing state.
@defaultValuetrue
Returns:image smoothing state
Since:12
/** * Gets the current image smoothing state. * * @defaultValue {@code true} * @return image smoothing state * @since 12 */
public boolean isImageSmoothing() { return curState.imageSmoothing; }
Resets the current path to empty. The default path is empty. The current path is a path attribute used for any of the path methods as specified in the Rendering Attributes Table and is not affected by the save() and restore() operations.
/** * Resets the current path to empty. * The default path is empty. * The current path is a <a href="#path-attr">path attribute</a> * used for any of the path methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a> * and <b>is not affected</b> by the {@link #save()} and * {@link #restore()} operations. */
public void beginPath() { path.reset(); markPathDirty(); }
Issues a move command for the current path to the given x,y coordinate. The coordinates are transformed by the current transform as they are added to the path and unaffected by subsequent changes to the transform. The current path is a path attribute used for any of the path methods as specified in the Rendering Attributes Table and is not affected by the save() and restore() operations.
Params:
  • x0 – the X position for the move to command.
  • y0 – the Y position for the move to command.
/** * Issues a move command for the current path to the given x,y coordinate. * The coordinates are transformed by the current transform as they are * added to the path and unaffected by subsequent changes to the transform. * The current path is a <a href="#path-attr">path attribute</a> * used for any of the path methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a> * and <b>is not affected</b> by the {@link #save()} and * {@link #restore()} operations. * * @param x0 the X position for the move to command. * @param y0 the Y position for the move to command. */
public void moveTo(double x0, double y0) { coords[0] = (float) x0; coords[1] = (float) y0; curState.transform.transform(coords, 0, coords, 0, 1); path.moveTo(coords[0], coords[1]); markPathDirty(); }
Adds segments to the current path to make a line to the given x,y coordinate. The coordinates are transformed by the current transform as they are added to the path and unaffected by subsequent changes to the transform. The current path is a path attribute used for any of the path methods as specified in the Rendering Attributes Table and is not affected by the save() and restore() operations.
Params:
  • x1 – the X coordinate of the ending point of the line.
  • y1 – the Y coordinate of the ending point of the line.
/** * Adds segments to the current path to make a line to the given x,y * coordinate. * The coordinates are transformed by the current transform as they are * added to the path and unaffected by subsequent changes to the transform. * The current path is a <a href="#path-attr">path attribute</a> * used for any of the path methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a> * and <b>is not affected</b> by the {@link #save()} and * {@link #restore()} operations. * * @param x1 the X coordinate of the ending point of the line. * @param y1 the Y coordinate of the ending point of the line. */
public void lineTo(double x1, double y1) { coords[0] = (float) x1; coords[1] = (float) y1; curState.transform.transform(coords, 0, coords, 0, 1); if (path.getNumCommands() == 0) { path.moveTo(coords[0], coords[1]); } path.lineTo(coords[0], coords[1]); markPathDirty(); }
Adds segments to the current path to make a quadratic Bezier curve. The coordinates are transformed by the current transform as they are added to the path and unaffected by subsequent changes to the transform. The current path is a path attribute used for any of the path methods as specified in the Rendering Attributes Table and is not affected by the save() and restore() operations.
Params:
  • xc – the X coordinate of the control point
  • yc – the Y coordinate of the control point
  • x1 – the X coordinate of the end point
  • y1 – the Y coordinate of the end point
/** * Adds segments to the current path to make a quadratic Bezier curve. * The coordinates are transformed by the current transform as they are * added to the path and unaffected by subsequent changes to the transform. * The current path is a <a href="#path-attr">path attribute</a> * used for any of the path methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a> * and <b>is not affected</b> by the {@link #save()} and * {@link #restore()} operations. * * @param xc the X coordinate of the control point * @param yc the Y coordinate of the control point * @param x1 the X coordinate of the end point * @param y1 the Y coordinate of the end point */
public void quadraticCurveTo(double xc, double yc, double x1, double y1) { coords[0] = (float) xc; coords[1] = (float) yc; coords[2] = (float) x1; coords[3] = (float) y1; curState.transform.transform(coords, 0, coords, 0, 2); if (path.getNumCommands() == 0) { path.moveTo(coords[0], coords[1]); } path.quadTo(coords[0], coords[1], coords[2], coords[3]); markPathDirty(); }
Adds segments to the current path to make a cubic Bezier curve. The coordinates are transformed by the current transform as they are added to the path and unaffected by subsequent changes to the transform. The current path is a path attribute used for any of the path methods as specified in the Rendering Attributes Table and is not affected by the save() and restore() operations.
Params:
  • xc1 – the X coordinate of first Bezier control point.
  • yc1 – the Y coordinate of the first Bezier control point.
  • xc2 – the X coordinate of the second Bezier control point.
  • yc2 – the Y coordinate of the second Bezier control point.
  • x1 – the X coordinate of the end point.
  • y1 – the Y coordinate of the end point.
/** * Adds segments to the current path to make a cubic Bezier curve. * The coordinates are transformed by the current transform as they are * added to the path and unaffected by subsequent changes to the transform. * The current path is a <a href="#path-attr">path attribute</a> * used for any of the path methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a> * and <b>is not affected</b> by the {@link #save()} and * {@link #restore()} operations. * * @param xc1 the X coordinate of first Bezier control point. * @param yc1 the Y coordinate of the first Bezier control point. * @param xc2 the X coordinate of the second Bezier control point. * @param yc2 the Y coordinate of the second Bezier control point. * @param x1 the X coordinate of the end point. * @param y1 the Y coordinate of the end point. */
public void bezierCurveTo(double xc1, double yc1, double xc2, double yc2, double x1, double y1) { coords[0] = (float) xc1; coords[1] = (float) yc1; coords[2] = (float) xc2; coords[3] = (float) yc2; coords[4] = (float) x1; coords[5] = (float) y1; curState.transform.transform(coords, 0, coords, 0, 3); if (path.getNumCommands() == 0) { path.moveTo(coords[0], coords[1]); } path.curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]); markPathDirty(); }
Adds segments to the current path to make an arc. The coordinates are transformed by the current transform as they are added to the path and unaffected by subsequent changes to the transform. The current path is a path attribute used for any of the path methods as specified in the Rendering Attributes Table and is not affected by the save() and restore() operations.

If p0 is the current point in the path and p1 is the point specified by (x1, y1) and p2 is the point specified by (x2, y2), then the arc segments appended will be segments along the circumference of a circle of the specified radius touching and inscribed into the convex (interior) side of p0->p1->p2. The path will contain a line segment (if needed) to the tangent point between that circle and p0->p1 followed by circular arc segments to reach the tangent point between the circle and p1->p2 and will end with the current point at that tangent point (not at p2). Note that the radius and circularity of the arc segments will be measured or considered relative to the current transform, but the resulting segments that are computed from those untransformed points will then be transformed when they are added to the path. Since all computation is done in untransformed space, but the pre-existing path segments are all transformed, the ability to correctly perform the computation may implicitly depend on being able to inverse transform the current end of the current path back into untransformed coordinates.

If there is no way to compute and inscribe the indicated circle for any reason then the entire operation will simply append segments to force a line to point p1. Possible reasons that the computation may fail include:

  • The current path is empty.
  • The segments p0->p1->p2 are colinear.
  • the current transform is non-invertible so that the current end point of the current path cannot be untransformed for computation.
Params:
  • x1 – the X coordinate of the first point of the arc.
  • y1 – the Y coordinate of the first point of the arc.
  • x2 – the X coordinate of the second point of the arc.
  • y2 – the Y coordinate of the second point of the arc.
  • radius – the radius of the arc in the range {0.0-positive infinity}.
/** * Adds segments to the current path to make an arc. * The coordinates are transformed by the current transform as they are * added to the path and unaffected by subsequent changes to the transform. * The current path is a <a href="#path-attr">path attribute</a> * used for any of the path methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a> * and <b>is not affected</b> by the {@link #save()} and * {@link #restore()} operations. * <p> * If {@code p0} is the current point in the path and {@code p1} is the * point specified by {@code (x1, y1)} and {@code p2} is the point * specified by {@code (x2, y2)}, then the arc segments appended will * be segments along the circumference of a circle of the specified * radius touching and inscribed into the convex (interior) side of * {@code p0->p1->p2}. The path will contain a line segment (if * needed) to the tangent point between that circle and {@code p0->p1} * followed by circular arc segments to reach the tangent point between * the circle and {@code p1->p2} and will end with the current point at * that tangent point (not at {@code p2}). * Note that the radius and circularity of the arc segments will be * measured or considered relative to the current transform, but the * resulting segments that are computed from those untransformed * points will then be transformed when they are added to the path. * Since all computation is done in untransformed space, but the * pre-existing path segments are all transformed, the ability to * correctly perform the computation may implicitly depend on being * able to inverse transform the current end of the current path back * into untransformed coordinates. * </p> * <p> * If there is no way to compute and inscribe the indicated circle * for any reason then the entire operation will simply append segments * to force a line to point {@code p1}. Possible reasons that the * computation may fail include: * <ul> * <li>The current path is empty.</li> * <li>The segments {@code p0->p1->p2} are colinear.</li> * <li>the current transform is non-invertible so that the current end * point of the current path cannot be untransformed for computation.</li> * </ul> * * @param x1 the X coordinate of the first point of the arc. * @param y1 the Y coordinate of the first point of the arc. * @param x2 the X coordinate of the second point of the arc. * @param y2 the Y coordinate of the second point of the arc. * @param radius the radius of the arc in the range {0.0-positive infinity}. */
public void arcTo(double x1, double y1, double x2, double y2, double radius) { if (path.getNumCommands() == 0) { moveTo(x1, y1); lineTo(x1, y1); } else if (!tryArcTo((float) x1, (float) y1, (float) x2, (float) y2, (float) radius)) { lineTo(x1, y1); } } private static double lenSq(double x0, double y0, double x1, double y1) { x1 -= x0; y1 -= y0; return x1 * x1 + y1 * y1; } private boolean tryArcTo(float x1, float y1, float x2, float y2, float radius) { float x0, y0; if (curState.transform.isTranslateOrIdentity()) { x0 = (float) (path.getCurrentX() - curState.transform.getMxt()); y0 = (float) (path.getCurrentY() - curState.transform.getMyt()); } else { coords[0] = path.getCurrentX(); coords[1] = path.getCurrentY(); try { curState.transform.inverseTransform(coords, 0, coords, 0, 1); } catch (NoninvertibleTransformException e) { return false; } x0 = coords[0]; y0 = coords[1]; } // call x1,y1 the corner point // If 2*theta is the angle described by p0->p1->p2 // then theta is the angle described by p0->p1->centerpt and // centerpt->p1->p2 // We know that the distance from the arc center to the tangent points // is r, and if A is the distance from the corner to the tangent point // then we know: // tan(theta) = r/A // A = r / sin(theta) // B = A * cos(theta) = r * (sin/cos) = r * tan // We use the cosine rule on the triangle to get the 2*theta angle: // cosB = (a^2 + c^2 - b^2) / (2ac) // where a and c are the adjacent sides and b is the opposite side // i.e. a = p0->p1, c=p1->p2, b=p0->p2 // Then we can use the tan^2 identity to compute B: // tan^2 = (1 - cos(2theta)) / (1 + cos(2theta)) double lsq01 = lenSq(x0, y0, x1, y1); double lsq12 = lenSq(x1, y1, x2, y2); double lsq02 = lenSq(x0, y0, x2, y2); double len01 = Math.sqrt(lsq01); double len12 = Math.sqrt(lsq12); double cosnum = lsq01 + lsq12 - lsq02; double cosden = 2.0 * len01 * len12; if (cosden == 0.0 || radius <= 0f) { return false; } double cos_2theta = cosnum / cosden; double tansq_den = (1.0 + cos_2theta); if (tansq_den == 0.0) { return false; } double tansq_theta = (1.0 - cos_2theta) / tansq_den; double A = radius / Math.sqrt(tansq_theta); double tx0 = x1 + (A / len01) * (x0 - x1); double ty0 = y1 + (A / len01) * (y0 - y1); double tx1 = x1 + (A / len12) * (x2 - x1); double ty1 = y1 + (A / len12) * (y2 - y1); // The midpoint between the two tangent points double mx = (tx0 + tx1) / 2.0; double my = (ty0 + ty1) / 2.0; // similar triangles tell us that: // len(m,center)/len(m,tangent) = len(m,tangent)/len(corner,m) // len(m,center) = lensq(m,tangent)/len(corner,m) // center = m + (m - p1) * len(m,center) / len(corner,m) // = m + (m - p1) * (lensq(m,tangent) / lensq(corner,m)) double lenratioden = lenSq(mx, my, x1, y1); if (lenratioden == 0.0) { return false; } double lenratio = lenSq(mx, my, tx0, ty0) / lenratioden; double cx = mx + (mx - x1) * lenratio; double cy = my + (my - y1) * lenratio; if (!(cx == cx && cy == cy)) { return false; } // Looks like we are good to draw, first we have to get to the // initial tangent point with a line segment. if (tx0 != x0 || ty0 != y0) { lineTo(tx0, ty0); } // We need sin(arc/2), cos(arc/2) // and possibly sin(arc/4), cos(arc/4) if we need 2 cubic beziers // We have tan(theta) = tan(tri/2) // arc = 180-tri // arc/2 = (180-tri)/2 = 90-(tri/2) // sin(arc/2) = sin(90-(tri/2)) = cos(tri/2) // cos(arc/2) = cos(90-(tri/2)) = sin(tri/2) // 2theta = tri, therefore theta = tri/2 // cos(tri/2)^2 = (1+cos(tri)) / 2.0 = (1+cos_2theta)/2.0 // sin(tri/2)^2 = (1-cos(tri)) / 2.0 = (1-cos_2theta)/2.0 // sin(arc/2) = cos(tri/2) = sqrt((1+cos_2theta)/2.0) // cos(arc/2) = sin(tri/2) = sqrt((1-cos_2theta)/2.0) // We compute cos(arc/2) here as we need it in either case below double coshalfarc = Math.sqrt((1.0 - cos_2theta) / 2.0); boolean ccw = (ty0 - cy) * (tx1 - cx) > (ty1 - cy) * (tx0 - cx); // If the arc covers more than 90 degrees then we must use 2 // cubic beziers to get a decent approximation. // arc = 180-tri // arc = 180-2*theta // arc > 90 implies 2*theta < 90 // 2*theta < 90 implies cos_2theta > 0 // So, we need 2 cubics if cos_2theta > 0 if (cos_2theta <= 0.0) { // 1 cubic bezier double sinhalfarc = Math.sqrt((1.0 + cos_2theta) / 2.0); double cv = 4.0 / 3.0 * sinhalfarc / (1.0 + coshalfarc); if (ccw) cv = -cv; double cpx0 = tx0 - cv * (ty0 - cy); double cpy0 = ty0 + cv * (tx0 - cx); double cpx1 = tx1 + cv * (ty1 - cy); double cpy1 = ty1 - cv * (tx1 - cx); bezierCurveTo(cpx0, cpy0, cpx1, cpy1, tx1, ty1); } else { // 2 cubic beziers // We need sin(arc/4) and cos(arc/4) // We computed cos(arc/2), so we can compute them as follows: // sin(arc/4) = sqrt((1 - cos(arc/2)) / 2) // cos(arc/4) = sart((1 + cos(arc/2)) / 2) double sinqtrarc = Math.sqrt((1.0 - coshalfarc) / 2.0); double cosqtrarc = Math.sqrt((1.0 + coshalfarc) / 2.0); double cv = 4.0 / 3.0 * sinqtrarc / (1.0 + cosqtrarc); if (ccw) cv = -cv; double midratio = radius / Math.sqrt(lenratioden); double midarcx = cx + (x1 - mx) * midratio; double midarcy = cy + (y1 - my) * midratio; double cpx0 = tx0 - cv * (ty0 - cy); double cpy0 = ty0 + cv * (tx0 - cx); double cpx1 = midarcx + cv * (midarcy - cy); double cpy1 = midarcy - cv * (midarcx - cx); bezierCurveTo(cpx0, cpy0, cpx1, cpy1, midarcx, midarcy); cpx0 = midarcx - cv * (midarcy - cy); cpy0 = midarcy + cv * (midarcx - cx); cpx1 = tx1 + cv * (ty1 - cy); cpy1 = ty1 - cv * (tx1 - cx); bezierCurveTo(cpx0, cpy0, cpx1, cpy1, tx1, ty1); } return true; }
Adds path elements to the current path to make an arc that uses Euclidean degrees. This Euclidean orientation sweeps from East to North, then West, then South, then back to East. The coordinates are transformed by the current transform as they are added to the path and unaffected by subsequent changes to the transform. The current path is a path attribute used for any of the path methods as specified in the Rendering Attributes Table and is not affected by the save() and restore() operations.
Params:
  • centerX – the center x position of the arc.
  • centerY – the center y position of the arc.
  • radiusX – the x radius of the arc.
  • radiusY – the y radius of the arc.
  • startAngle – the starting angle of the arc in the range 0-360.0
  • length – the length of the baseline of the arc.
/** * Adds path elements to the current path to make an arc that uses Euclidean * degrees. This Euclidean orientation sweeps from East to North, then West, * then South, then back to East. * The coordinates are transformed by the current transform as they are * added to the path and unaffected by subsequent changes to the transform. * The current path is a <a href="#path-attr">path attribute</a> * used for any of the path methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a> * and <b>is not affected</b> by the {@link #save()} and * {@link #restore()} operations. * * @param centerX the center x position of the arc. * @param centerY the center y position of the arc. * @param radiusX the x radius of the arc. * @param radiusY the y radius of the arc. * @param startAngle the starting angle of the arc in the range {@code 0-360.0} * @param length the length of the baseline of the arc. */
public void arc(double centerX, double centerY, double radiusX, double radiusY, double startAngle, double length) { Arc2D arc = new Arc2D((float) (centerX - radiusX), // x (float) (centerY - radiusY), // y (float) (radiusX * 2.0), // w (float) (radiusY * 2.0), // h (float) startAngle, (float) length, Arc2D.OPEN); path.append(arc.getPathIterator(curState.transform), true); markPathDirty(); }
Adds path elements to the current path to make a rectangle. The coordinates are transformed by the current transform as they are added to the path and unaffected by subsequent changes to the transform. The current path is a path attribute used for any of the path methods as specified in the Rendering Attributes Table and is not affected by the save() and restore() operations.
Params:
  • x – x position of the upper left corner of the rectangle.
  • y – y position of the upper left corner of the rectangle.
  • w – width of the rectangle.
  • h – height of the rectangle.
/** * Adds path elements to the current path to make a rectangle. * The coordinates are transformed by the current transform as they are * added to the path and unaffected by subsequent changes to the transform. * The current path is a <a href="#path-attr">path attribute</a> * used for any of the path methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a> * and <b>is not affected</b> by the {@link #save()} and * {@link #restore()} operations. * * @param x x position of the upper left corner of the rectangle. * @param y y position of the upper left corner of the rectangle. * @param w width of the rectangle. * @param h height of the rectangle. */
public void rect(double x, double y, double w, double h) { coords[0] = (float) x; coords[1] = (float) y; coords[2] = (float) w; coords[3] = (float) 0; coords[4] = (float) 0; coords[5] = (float) h; curState.transform.deltaTransform(coords, 0, coords, 0, 3); float x0 = coords[0] + (float) curState.transform.getMxt(); float y0 = coords[1] + (float) curState.transform.getMyt(); float dx1 = coords[2]; float dy1 = coords[3]; float dx2 = coords[4]; float dy2 = coords[5]; path.moveTo(x0, y0); path.lineTo(x0+dx1, y0+dy1); path.lineTo(x0+dx1+dx2, y0+dy1+dy2); path.lineTo(x0+dx2, y0+dy2); path.closePath(); markPathDirty(); // path.moveTo(x0, y0); // not needed, closepath leaves pen at moveto }
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 null value or incorrect SVG path will be ignored. The coordinates are transformed by the current transform as they are added to the path and unaffected by subsequent changes to the transform. The current path is a path attribute used for any of the path methods as specified in the Rendering Attributes Table and is not affected by the save() and restore() operations.
Params:
  • svgpath – the SVG Path string.
/** * 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. * The coordinates are transformed by the current transform as they are * added to the path and unaffected by subsequent changes to the transform. * The current path is a <a href="#path-attr">path attribute</a> * used for any of the path methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a> * and <b>is not affected</b> by the {@link #save()} and * {@link #restore()} operations. * * @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++) { switch (svgpath.charAt(i)) { case ' ': case '\t': case '\r': case '\n': continue; case 'M': prependMoveto = skipMoveto = false; break; case 'm': if (path.getNumCommands() == 0) { // An initial relative moveTo becomes absolute prependMoveto = false; } // Even if we prepend an initial moveTo in the temp // path, we do not want to delete the resulting initial // moveTo because the relative moveto will be folded // into it by an optimization in the Path2D object. skipMoveto = false; break; } break; } Path2D p2d = new Path2D(); if (prependMoveto && path.getNumCommands() > 0) { float x0, y0; if (curState.transform.isTranslateOrIdentity()) { x0 = (float) (path.getCurrentX() - curState.transform.getMxt()); y0 = (float) (path.getCurrentY() - curState.transform.getMyt()); } else { coords[0] = path.getCurrentX(); coords[1] = path.getCurrentY(); try { curState.transform.inverseTransform(coords, 0, coords, 0, 1); } catch (NoninvertibleTransformException e) { } x0 = coords[0]; y0 = coords[1]; } p2d.moveTo(x0, y0); } else { skipMoveto = false; } 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 } }
Closes the path. The current path is a path attribute used for any of the path methods as specified in the Rendering Attributes Table and is not affected by the save() and restore() operations.
/** * Closes the path. * The current path is a <a href="#path-attr">path attribute</a> * used for any of the path methods as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a> * and <b>is not affected</b> by the {@link #save()} and * {@link #restore()} operations. */
public void closePath() { if (path.getNumCommands() > 0) { path.closePath(); markPathDirty(); } }
Fills the path with the current fill paint.

This method will be affected by any of the global common, fill, or path attributes as specified in the Rendering Attributes Table. Note that the path segments were transformed as they were originally added to the current path so the current transform will not affect those path segments again, but it may affect other attributes in affect at the time of the fill() operation.

/** * Fills the path with the current fill paint. * <p> * This method will be affected by any of the * <a href="#comm-attr">global common</a>, * <a href="#fill-attr">fill</a>, * or <a href="#path-attr">path</a> * attributes as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * Note that the path segments were transformed as they were originally * added to the current path so the current transform will not affect * those path segments again, but it may affect other attributes in * affect at the time of the {@code fill()} operation. * </p> */
public void fill() { writePath(NGCanvas.FILL_PATH); }
Strokes the path with the current stroke paint.

This method will be affected by any of the global common, stroke, or path attributes as specified in the Rendering Attributes Table. Note that the path segments were transformed as they were originally added to the current path so the current transform will not affect those path segments again, but it may affect other attributes in affect at the time of the stroke() operation.

/** * Strokes the path with the current stroke paint. * <p> * This method will be affected by any of the * <a href="#comm-attr">global common</a>, * <a href="#strk-attr">stroke</a>, * or <a href="#path-attr">path</a> * attributes as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * Note that the path segments were transformed as they were originally * added to the current path so the current transform will not affect * those path segments again, but it may affect other attributes in * affect at the time of the {@code stroke()} operation. * </p> */
public void stroke() { writePath(NGCanvas.STROKE_PATH); }
Intersects the current clip with the current path and applies it to subsequent rendering operation as an anti-aliased mask. The current clip is a common attribute used for nearly all rendering operations as specified in the Rendering Attributes Table.

This method will itself be affected only by the path attributes as specified in the Rendering Attributes Table. Note that the path segments were transformed as they were originally added to the current path so the current transform will not affect those path segments again, but it may affect other attributes in affect at the time of the stroke() operation.

/** * Intersects the current clip with the current path and applies it to * subsequent rendering operation as an anti-aliased mask. * The current clip is a <a href="#comm-attr">common attribute</a> * used for nearly all rendering operations as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * <p> * This method will itself be affected only by the * <a href="#path-attr">path</a> * attributes as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * Note that the path segments were transformed as they were originally * added to the current path so the current transform will not affect * those path segments again, but it may affect other attributes in * affect at the time of the {@code stroke()} operation. * </p> */
public void clip() { Path2D clip = new Path2D(path); clipStack.addLast(clip); curState.numClipPaths++; GrowableDataBuffer buf = getBuffer(); buf.putByte(NGCanvas.PUSH_CLIP); buf.putObject(clip); }
Returns true if the the given x,y point is inside the path.
Params:
  • x – the X coordinate to use for the check.
  • y – the Y coordinate to use for the check.
Returns:true if the point given is inside the path, false otherwise.
/** * Returns true if the the given x,y point is inside the path. * * @param x the X coordinate to use for the check. * @param y the Y coordinate to use for the check. * @return true if the point given is inside the path, false * otherwise. */
public boolean isPointInPath(double x, double y) { // TODO: HTML5 considers points on the path to be inside, but we // implement a halfin-halfout approach... return path.contains((float) x, (float) y); }
Clears a portion of the canvas with a transparent color value.

This method will be affected only by the current transform, clip, and effect.

Params:
  • x – X position of the upper left corner of the rectangle.
  • y – Y position of the upper left corner of the rectangle.
  • w – width of the rectangle.
  • h – height of the rectangle.
/** * Clears a portion of the canvas with a transparent color value. * <p> * This method will be affected only by the current transform, clip, * and effect. * </p> * * @param x X position of the upper left corner of the rectangle. * @param y Y position of the upper left corner of the rectangle. * @param w width of the rectangle. * @param h height of the rectangle. */
public void clearRect(double x, double y, double w, double h) { if (w != 0 && h != 0) { resetIfCovers(null, x, y, w, h); writeOp4(x, y, w, h, NGCanvas.CLEAR_RECT); } }
Fills a rectangle using the current fill paint.

This method will be affected by any of the global common or fill attributes as specified in the Rendering Attributes Table.

Params:
  • x – the X position of the upper left corner of the rectangle.
  • y – the Y position of the upper left corner of the rectangle.
  • w – the width of the rectangle.
  • h – the height of the rectangle.
/** * Fills a rectangle using the current fill paint. * <p> * This method will be affected by any of the * <a href="#comm-attr">global common</a> * or <a href="#fill-attr">fill</a> * attributes as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * </p> * * @param x the X position of the upper left corner of the rectangle. * @param y the Y position of the upper left corner of the rectangle. * @param w the width of the rectangle. * @param h the height of the rectangle. */
public void fillRect(double x, double y, double w, double h) { if (w != 0 && h != 0) { resetIfCovers(this.curState.fill, x, y, w, h); writeOp4(x, y, w, h, NGCanvas.FILL_RECT); } }
Strokes a rectangle using the current stroke paint.

This method will be affected by any of the global common or stroke attributes as specified in the Rendering Attributes Table.

Params:
  • x – the X position of the upper left corner of the rectangle.
  • y – the Y position of the upper left corner of the rectangle.
  • w – the width of the rectangle.
  • h – the height of the rectangle.
/** * Strokes a rectangle using the current stroke paint. * <p> * This method will be affected by any of the * <a href="#comm-attr">global common</a> * or <a href="#strk-attr">stroke</a> * attributes as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * </p> * * @param x the X position of the upper left corner of the rectangle. * @param y the Y position of the upper left corner of the rectangle. * @param w the width of the rectangle. * @param h the height of the rectangle. */
public void strokeRect(double x, double y, double w, double h) { if (w != 0 || h != 0) { writeOp4(x, y, w, h, NGCanvas.STROKE_RECT); } }
Fills an oval using the current fill paint.

This method will be affected by any of the global common or fill attributes as specified in the Rendering Attributes Table.

Params:
  • x – the X coordinate of the upper left bound of the oval.
  • y – the Y coordinate of the upper left bound of the oval.
  • w – the width at the center of the oval.
  • h – the height at the center of the oval.
/** * Fills an oval using the current fill paint. * <p> * This method will be affected by any of the * <a href="#comm-attr">global common</a> * or <a href="#fill-attr">fill</a> * attributes as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * </p> * * @param x the X coordinate of the upper left bound of the oval. * @param y the Y coordinate of the upper left bound of the oval. * @param w the width at the center of the oval. * @param h the height at the center of the oval. */
public void fillOval(double x, double y, double w, double h) { if (w != 0 && h != 0) { writeOp4(x, y, w, h, NGCanvas.FILL_OVAL); } }
Strokes an oval using the current stroke paint.

This method will be affected by any of the global common or stroke attributes as specified in the Rendering Attributes Table.

Params:
  • x – the X coordinate of the upper left bound of the oval.
  • y – the Y coordinate of the upper left bound of the oval.
  • w – the width at the center of the oval.
  • h – the height at the center of the oval.
/** * Strokes an oval using the current stroke paint. * <p> * This method will be affected by any of the * <a href="#comm-attr">global common</a> * or <a href="#strk-attr">stroke</a> * attributes as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * </p> * * @param x the X coordinate of the upper left bound of the oval. * @param y the Y coordinate of the upper left bound of the oval. * @param w the width at the center of the oval. * @param h the height at the center of the oval. */
public void strokeOval(double x, double y, double w, double h) { if (w != 0 || h != 0) { writeOp4(x, y, w, h, NGCanvas.STROKE_OVAL); } }
Fills an arc using the current fill paint. A null ArcType or non positive width or height will cause the render command to be ignored.

This method will be affected by any of the global common or fill attributes as specified in the Rendering Attributes Table.

Params:
  • x – the X coordinate of the arc.
  • y – the Y coordinate of the arc.
  • w – the width of the arc.
  • h – the height of the arc.
  • startAngle – the starting angle of the arc in degrees.
  • arcExtent – the angular extent of the arc in degrees.
  • closure – closure type (Round, Chord, Open) or null.
/** * Fills an arc using the current fill paint. A {@code null} ArcType or * non positive width or height will cause the render command to be ignored. * <p> * This method will be affected by any of the * <a href="#comm-attr">global common</a> * or <a href="#fill-attr">fill</a> * attributes as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * </p> * * @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 the angular extent of the arc in degrees. * @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) { if (w != 0 && h != 0 && closure != null) { writeArcType(closure); writeOp6(x, y, w, h, startAngle, arcExtent, NGCanvas.FILL_ARC); } }
Strokes an Arc using the current stroke paint. A null ArcType or non positive width or height will cause the render command to be ignored.

This method will be affected by any of the global common or stroke attributes as specified in the Rendering Attributes Table.

Params:
  • x – the X coordinate of the arc.
  • y – the Y coordinate of the arc.
  • w – the width of the arc.
  • h – the height of the arc.
  • startAngle – the starting angle of the arc in degrees.
  • arcExtent – arcExtent the angular extent of the arc in degrees.
  • closure – closure type (Round, Chord, Open) or null
/** * 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. * <p> * This method will be affected by any of the * <a href="#comm-attr">global common</a> * or <a href="#strk-attr">stroke</a> * attributes as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * </p> * * @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) or null */
public void strokeArc(double x, double y, double w, double h, double startAngle, double arcExtent, ArcType closure) { if (w != 0 && h != 0 && closure != null) { writeArcType(closure); writeOp6(x, y, w, h, startAngle, arcExtent, NGCanvas.STROKE_ARC); } }
Fills a rounded rectangle using the current fill paint.

This method will be affected by any of the global common or fill attributes as specified in the Rendering Attributes Table.

Params:
  • x – the X coordinate of the upper left bound of the oval.
  • y – the Y coordinate of the upper left bound of the oval.
  • w – the width at the center of the oval.
  • h – the height at the center of the oval.
  • arcWidth – the arc width of the rectangle corners.
  • arcHeight – the arc height of the rectangle corners.
/** * Fills a rounded rectangle using the current fill paint. * <p> * This method will be affected by any of the * <a href="#comm-attr">global common</a> * or <a href="#fill-attr">fill</a> * attributes as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * </p> * * @param x the X coordinate of the upper left bound of the oval. * @param y the Y coordinate of the upper left bound of the oval. * @param w the width at the center of the oval. * @param h the height at the center of the oval. * @param arcWidth the arc width of the rectangle corners. * @param arcHeight the arc height of the rectangle corners. */
public void fillRoundRect(double x, double y, double w, double h, double arcWidth, double arcHeight) { if (w != 0 && h != 0) { writeOp6(x, y, w, h, arcWidth, arcHeight, NGCanvas.FILL_ROUND_RECT); } }
Strokes a rounded rectangle using the current stroke paint.

This method will be affected by any of the global common or stroke attributes as specified in the Rendering Attributes Table.

Params:
  • x – the X coordinate of the upper left bound of the oval.
  • y – the Y coordinate of the upper left bound of the oval.
  • w – the width at the center of the oval.
  • h – the height at the center of the oval.
  • arcWidth – the arc width of the rectangle corners.
  • arcHeight – the arc height of the rectangle corners.
/** * Strokes a rounded rectangle using the current stroke paint. * <p> * This method will be affected by any of the * <a href="#comm-attr">global common</a> * or <a href="#strk-attr">stroke</a> * attributes as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * </p> * * @param x the X coordinate of the upper left bound of the oval. * @param y the Y coordinate of the upper left bound of the oval. * @param w the width at the center of the oval. * @param h the height at the center of the oval. * @param arcWidth the arc width of the rectangle corners. * @param arcHeight the arc height of the rectangle corners. */
public void strokeRoundRect(double x, double y, double w, double h, double arcWidth, double arcHeight) { if (w != 0 && h != 0) { writeOp6(x, y, w, h, arcWidth, arcHeight, NGCanvas.STROKE_ROUND_RECT); } }
Strokes a line using the current stroke paint.

This method will be affected by any of the global common or stroke attributes as specified in the Rendering Attributes Table.

Params:
  • x1 – the X coordinate of the starting point of the line.
  • y1 – the Y coordinate of the starting point of the line.
  • x2 – the X coordinate of the ending point of the line.
  • y2 – the Y coordinate of the ending point of the line.
/** * Strokes a line using the current stroke paint. * <p> * This method will be affected by any of the * <a href="#comm-attr">global common</a> * or <a href="#strk-attr">stroke</a> * attributes as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * </p> * * @param x1 the X coordinate of the starting point of the line. * @param y1 the Y coordinate of the starting point of the line. * @param x2 the X coordinate of the ending point of the line. * @param y2 the Y coordinate of the ending point of the line. */
public void strokeLine(double x1, double y1, double x2, double y2) { writeOp4(x1, y1, x2, y2, NGCanvas.STROKE_LINE); }
Fills a polygon with the given points using the currently set fill paint. A null value for any of the arrays will be ignored and nothing will be drawn.

This method will be affected by any of the global common, fill, or Fill Rule attributes as specified in the Rendering Attributes Table.

Params:
  • xPoints – array containing the x coordinates of the polygon's points or null.
  • yPoints – array containing the y coordinates of the polygon's points or null.
  • nPoints – the number of points that make the polygon.
/** * Fills a polygon with the given points using the currently set fill paint. * A {@code null} value for any of the arrays will be ignored and nothing will be drawn. * <p> * This method will be affected by any of the * <a href="#comm-attr">global common</a>, * <a href="#fill-attr">fill</a>, * or <a href="#path-attr">Fill Rule</a> * attributes as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * </p> * * @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) { if (nPoints >= 3) { writePoly(xPoints, yPoints, nPoints, true, NGCanvas.FILL_PATH); } }
Strokes a polygon with the given points using the currently set stroke paint. A null value for any of the arrays will be ignored and nothing will be drawn.

This method will be affected by any of the global common or stroke attributes as specified in the Rendering Attributes Table.

Params:
  • xPoints – array containing the x coordinates of the polygon's points or null.
  • yPoints – array containing the y coordinates of the polygon's points or null.
  • nPoints – the number of points that make the polygon.
/** * Strokes a polygon with the given points using the currently set stroke paint. * A {@code null} value for any of the arrays will be ignored and nothing will be drawn. * <p> * This method will be affected by any of the * <a href="#comm-attr">global common</a> * or <a href="#strk-attr">stroke</a> * attributes as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * </p> * * @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) { if (nPoints >= 2) { writePoly(xPoints, yPoints, nPoints, true, NGCanvas.STROKE_PATH); } }
Strokes a polyline with the given points using the currently set stroke paint attribute. A null value for any of the arrays will be ignored and nothing will be drawn.

This method will be affected by any of the global common or stroke attributes as specified in the Rendering Attributes Table.

Params:
  • xPoints – array containing the x coordinates of the polyline's points or null.
  • yPoints – array containing the y coordinates of the polyline's points or null.
  • nPoints – the number of points that make the polyline.
/** * Strokes a polyline with the given points using the currently set stroke * paint attribute. * A {@code null} value for any of the arrays will be ignored and nothing will be drawn. * <p> * This method will be affected by any of the * <a href="#comm-attr">global common</a> * or <a href="#strk-attr">stroke</a> * attributes as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * </p> * * @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) { if (nPoints >= 2) { writePoly(xPoints, yPoints, nPoints, false, NGCanvas.STROKE_PATH); } }
Draws an image at the given x, y position using the width and height of the given image. A null image value or an image still in progress will be ignored.

This method will be affected by any of the global common or image attributes as specified in the Rendering Attributes Table.

Params:
  • img – the image to be drawn or null.
  • x – the X coordinate on the destination for the upper left of the image.
  • y – the Y coordinate on the destination for the upper left of the image.
/** * 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. * <p> * This method will be affected by any of the * <a href="#comm-attr">global common</a> * or <a href="#image-attr">image</a> * attributes as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * </p> * * @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); }
Draws an image into the given destination rectangle of the canvas. The Image is scaled to fit into the destination rectangle. A null image value or an image still in progress will be ignored.

This method will be affected by any of the global common or image attributes as specified in the Rendering Attributes Table.

Params:
  • img – the image to be drawn or null.
  • x – the X coordinate on the destination for the upper left of the image.
  • y – the Y coordinate on the destination for the upper left of the image.
  • w – the width of the destination rectangle.
  • h – the height of the destination rectangle.
/** * Draws an image into the given destination rectangle of the canvas. The * Image is scaled to fit into the destination rectangle. * A {@code null} image value or an image still in progress will be ignored. * <p> * This method will be affected by any of the * <a href="#comm-attr">global common</a> * or <a href="#image-attr">image</a> * attributes as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * </p> * * @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. * @param h the height of the destination rectangle. */
public void drawImage(Image img, double x, double y, double w, double h) { writeImage(img, x, y, w, h); }
Draws the specified source rectangle of the given image to the given destination rectangle of the Canvas. A null image value or an image still in progress will be ignored.

This method will be affected by any of the global common or image attributes as specified in the Rendering Attributes Table.

Params:
  • img – the image to be drawn or null.
  • sx – the source rectangle's X coordinate position.
  • sy – the source rectangle's Y coordinate position.
  • sw – the source rectangle's width.
  • sh – the source rectangle's height.
  • dx – the destination rectangle's X coordinate position.
  • dy – the destination rectangle's Y coordinate position.
  • dw – the destination rectangle's width.
  • dh – the destination rectangle's height.
/** * Draws the specified 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. * <p> * This method will be affected by any of the * <a href="#comm-attr">global common</a> * or <a href="#image-attr">image</a> * attributes as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * </p> * * @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. * @param sh the source rectangle's height. * @param dx the destination rectangle's X coordinate position. * @param dy the destination rectangle's Y coordinate position. * @param dw the destination rectangle's width. * @param dh the destination rectangle's height. */
public void drawImage(Image img, double sx, double sy, double sw, double sh, double dx, double dy, double dw, double dh) { writeImage(img, dx, dy, dw, dh, sx, sy, sw, sh); } private PixelWriter writer;
Returns a PixelWriter object that can be used to modify the pixels of the Canvas associated with this GraphicsContext. All coordinates in the PixelWriter methods on the returned object will be in device space since they refer directly to pixels and no other rendering attributes will be applied when modifying pixels using this object.
Returns:the PixelWriter for modifying the pixels of this Canvas
/** * Returns a {@link PixelWriter} object that can be used to modify * the pixels of the {@link Canvas} associated with this * {@code GraphicsContext}. * All coordinates in the {@code PixelWriter} methods on the returned * object will be in device space since they refer directly to pixels * and no other rendering attributes will be applied when modifying * pixels using this object. * * @return the {@code PixelWriter} for modifying the pixels of this * {@code Canvas} */
public PixelWriter getPixelWriter() { if (writer == null) { writer = new PixelWriter() { @Override public PixelFormat<ByteBuffer> getPixelFormat() { return PixelFormat.getByteBgraPreInstance(); } private BytePixelSetter getSetter() { return ByteBgraPre.setter; } @Override public void setArgb(int x, int y, int argb) { GrowableDataBuffer buf = getBuffer(); buf.putByte(NGCanvas.PUT_ARGB); buf.putInt(x); buf.putInt(y); buf.putInt(argb); } @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); int b = (int) Math.round(c.getBlue() * 255.0); setArgb(x, y, (a << 24) | (r << 16) | (g << 8) | b); } private void writePixelBuffer(int x, int y, int w, int h, byte[] pixels) { GrowableDataBuffer buf = getBuffer(); buf.putByte(NGCanvas.PUT_ARGBPRE_BUF); buf.putInt(x); buf.putInt(y); buf.putInt(w); buf.putInt(h); buf.putObject(pixels); } private int[] checkBounds(int x, int y, int w, int h, PixelFormat<? extends Buffer> pf, int scan) { // assert (w >= 0 && h >= 0) - checked by caller int cw = (int) Math.ceil(theCanvas.getWidth()); int ch = (int) Math.ceil(theCanvas.getHeight()); if (x >= 0 && y >= 0 && x+w <= cw && y+h <= ch) { return null; } int offset = 0; if (x < 0) { w += x; if (w < 0) return null; if (pf != null) { switch (pf.getType()) { case BYTE_BGRA: case BYTE_BGRA_PRE: offset -= x * 4; break; case BYTE_RGB: offset -= x * 3; break; case BYTE_INDEXED: case INT_ARGB: case INT_ARGB_PRE: offset -= x; break; default: throw new InternalError("unknown Pixel Format"); } } x = 0; } if (y < 0) { h += y; if (h < 0) return null; offset -= y * scan; y = 0; } if (x + w > cw) { w = cw - x; if (w < 0) return null; } if (y + h > ch) { h = ch - y; if (h < 0) return null; } return new int[] { x, y, w, h, offset }; } @Override public <T extends Buffer> void setPixels(int x, int y, int w, int h, 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, pixelformat, scan); if (adjustments != null) { x = adjustments[0]; y = adjustments[1]; w = adjustments[2]; h = adjustments[3]; offset += adjustments[4]; } byte pixels[] = new byte[w * h * 4]; ByteBuffer dst = ByteBuffer.wrap(pixels); PixelGetter<T> getter = PixelUtils.getGetter(pixelformat); PixelConverter<T, ByteBuffer> converter = PixelUtils.getConverter(getter, getSetter()); converter.convert(buffer, offset, scan, dst, 0, w * 4, w, h); writePixelBuffer(x, y, w, h, pixels); } @Override public void setPixels(int x, int y, int w, int h, 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); if (adjustments != null) { x = adjustments[0]; y = adjustments[1]; w = adjustments[2]; h = adjustments[3]; offset += adjustments[4]; } byte pixels[] = new byte[w * h * 4]; BytePixelGetter getter = PixelUtils.getByteGetter(pixelformat); ByteToBytePixelConverter converter = PixelUtils.getB2BConverter(getter, getSetter()); converter.convert(buffer, offset, scanlineStride, pixels, 0, w * 4, w, h); writePixelBuffer(x, y, w, h, pixels); } @Override public void setPixels(int x, int y, int w, int h, 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); if (adjustments != null) { x = adjustments[0]; y = adjustments[1]; w = adjustments[2]; h = adjustments[3]; offset += adjustments[4]; } byte pixels[] = new byte[w * h * 4]; IntPixelGetter getter = PixelUtils.getIntGetter(pixelformat); IntToBytePixelConverter converter = PixelUtils.getI2BConverter(getter, getSetter()); converter.convert(buffer, offset, scanlineStride, pixels, 0, w * 4, w, h); writePixelBuffer(x, y, w, h, pixels); } @Override 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) { int newx = adjustments[0]; int newy = adjustments[1]; srcx += newx - dstx; srcy += newy - dsty; dstx = newx; dsty = newy; w = adjustments[2]; h = adjustments[3]; } byte pixels[] = new byte[w * h * 4]; reader.getPixels(srcx, srcy, w, h, PixelFormat.getByteBgraPreInstance(), pixels, 0, w * 4); writePixelBuffer(dstx, dsty, w, h, pixels); } }; } return writer; }
Sets the effect to be applied after the next draw call, or null to disable effects. The current effect is a common attribute used for nearly all rendering operations as specified in the Rendering Attributes Table.
Params:
  • e – the effect to use, or null to disable effects
/** * Sets the effect to be applied after the next draw call, or null to * disable effects. * The current effect is a <a href="#comm-attr">common attribute</a> * used for nearly all rendering operations as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * * @param e the effect to use, or null to disable effects */
public void setEffect(Effect e) { GrowableDataBuffer buf = getBuffer(); buf.putByte(NGCanvas.EFFECT); if (e == null) { curState.effect = null; buf.putObject(null); } else { curState.effect = EffectHelper.copy(e); EffectHelper.sync(curState.effect); buf.putObject(EffectHelper.getPeer(curState.effect)); } }
Gets a copy of the effect to be applied after the next draw call. A null return value means that no effect will be applied after subsequent rendering calls. The current effect is a common attribute used for nearly all rendering operations as specified in the Rendering Attributes Table.
Params:
  • e – an Effect object that may be used to store the copy of the current effect, if it is of a compatible type
Returns:the current effect used for all rendering calls, or null if there is no current effect
/** * Gets a copy of the effect to be applied after the next draw call. * A null return value means that no effect will be applied after subsequent * rendering calls. * The current effect is a <a href="#comm-attr">common attribute</a> * used for nearly all rendering operations as specified in the * <a href="#attr-ops-table">Rendering Attributes Table</a>. * * @param e an {@code Effect} object that may be used to store the * copy of the current effect, if it is of a compatible type * @return the current effect used for all rendering calls, * or null if there is no current effect */
public Effect getEffect(Effect e) { return curState.effect == null ? null : EffectHelper.copy(curState.effect); }
Applies the given effect to the entire bounds of the canvas and stores the result back into the same canvas. A null value will be ignored. The effect will be applied without any other rendering attributes and under an Identity coordinate transform. Since the effect is applied to the entire bounds of the canvas, some effects may have a confusing result, such as a Reflection effect that will apply its reflection off of the bottom of the canvas even if only a portion of the canvas has been rendered to and will not be visible unless a negative offset is used to bring the reflection back into view.
Params:
  • e – the effect to apply onto the entire destination or null.
/** * Applies the given effect to the entire bounds of the canvas and stores * the result back into the same canvas. * A {@code null} value will be ignored. * The effect will be applied without any other rendering attributes and * under an Identity coordinate transform. * Since the effect is applied to the entire bounds of the canvas, some * effects may have a confusing result, such as a Reflection effect * that will apply its reflection off of the bottom of the canvas even if * only a portion of the canvas has been rendered to and will not be * visible unless a negative offset is used to bring the reflection back * into view. * * @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 = EffectHelper.copy(e); EffectHelper.sync(effect); buf.putObject(EffectHelper.getPeer(effect)); } }