Java tutorial
/* * Copyright (c) 2002-2015 Gargoyle Software Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.gargoylesoftware.htmlunit.javascript.host.canvas; import static com.gargoylesoftware.htmlunit.javascript.configuration.BrowserName.CHROME; import static com.gargoylesoftware.htmlunit.javascript.configuration.BrowserName.FF; import static com.gargoylesoftware.htmlunit.javascript.configuration.BrowserName.IE; import java.awt.Color; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.lang.reflect.Field; import javax.imageio.ImageIO; import javax.imageio.ImageReader; import org.apache.commons.codec.binary.Base64; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.gargoylesoftware.htmlunit.html.HtmlImage; import com.gargoylesoftware.htmlunit.javascript.SimpleScriptable; import com.gargoylesoftware.htmlunit.javascript.configuration.JsxClass; import com.gargoylesoftware.htmlunit.javascript.configuration.JsxConstructor; import com.gargoylesoftware.htmlunit.javascript.configuration.JsxFunction; import com.gargoylesoftware.htmlunit.javascript.configuration.JsxGetter; import com.gargoylesoftware.htmlunit.javascript.configuration.JsxSetter; import com.gargoylesoftware.htmlunit.javascript.configuration.WebBrowser; import com.gargoylesoftware.htmlunit.javascript.host.html.HTMLCanvasElement; import com.gargoylesoftware.htmlunit.javascript.host.html.HTMLImageElement; import net.sourceforge.htmlunit.corejs.javascript.Context; import net.sourceforge.htmlunit.corejs.javascript.Undefined; /** * A JavaScript object for {@code CanvasRenderingContext2D}. * * @version $Revision$ * @author Ahmed Ashour * @author Marc Guillemot * @author Frank Danek * @author Ronald Brill */ @JsxClass(browsers = { @WebBrowser(CHROME), @WebBrowser(FF), @WebBrowser(value = IE, minVersion = 11) }) public class CanvasRenderingContext2D extends SimpleScriptable { private static final Log LOG = LogFactory.getLog(CanvasRenderingContext2D.class); private final HTMLCanvasElement canvas_; private final BufferedImage image_; private final Graphics2D graphics2D_; /** * Default constructor. */ @JsxConstructor({ @WebBrowser(CHROME), @WebBrowser(FF) }) public CanvasRenderingContext2D() { canvas_ = null; image_ = null; graphics2D_ = null; } /** * Constructs in association with {@link HTMLCanvasElement}. * @param canvas the {@link HTMLCanvasElement} */ public CanvasRenderingContext2D(final HTMLCanvasElement canvas) { canvas_ = canvas; image_ = new BufferedImage(canvas.getWidth(), canvas.getHeight(), BufferedImage.TYPE_INT_RGB); graphics2D_ = image_.createGraphics(); } /** * Returns the "fillStyle" property. * @return the "fillStyle" property */ @JsxGetter public Object getFillStyle() { return null; } /** * Sets the "fillStyle" property. * @param fillStyle the "fillStyle" property */ @JsxSetter public void setFillStyle(String fillStyle) { fillStyle = fillStyle.replaceAll("\\s", ""); Color color = null; if (fillStyle.startsWith("rgb(")) { final String[] colors = fillStyle.substring(4, fillStyle.length() - 1).split(","); color = new Color(Integer.parseInt(colors[0]), Integer.parseInt(colors[1]), Integer.parseInt(colors[2])); } else if (fillStyle.startsWith("rgba(")) { final String[] colors = fillStyle.substring(5, fillStyle.length() - 1).split(","); color = new Color(Integer.parseInt(colors[0]), Integer.parseInt(colors[1]), Integer.parseInt(colors[2]), (int) (Float.parseFloat(colors[3]) * 255)); } else if (fillStyle.startsWith("#")) { color = Color.decode(fillStyle); } else { try { final Field f = Color.class.getField(fillStyle); color = (Color) f.get(null); } catch (final Exception e) { LOG.info("Can not find color '" + fillStyle + '\''); color = Color.black; } } graphics2D_.setColor(color); } /** * Returns the "strokeStyle" property. * @return the "strokeStyle" property */ @JsxGetter public Object getStrokeStyle() { return null; } /** * Sets the "strokeStyle" property. * @param strokeStyle the "strokeStyle" property */ @JsxSetter public void setStrokeStyle(final Object strokeStyle) { //empty } /** * Returns the "lineWidth" property. * @return the "lineWidth" property */ @JsxGetter public double getLineWidth() { return 0; } /** * Sets the "lineWidth" property. * @param lineWidth the "lineWidth" property */ @JsxSetter public void setLineWidth(final Object lineWidth) { //empty } /** * Returns the "globalAlpha" property. * @return the "globalAlpha" property */ @JsxGetter public double getGlobalAlpha() { return 0; } /** * Sets the "globalAlpha" property. * @param globalAlpha the "globalAlpha" property */ @JsxSetter public void setGlobalAlpha(final Object globalAlpha) { //empty } /** * Draws an arc. * @param x the x * @param y the y * @param radius the radius * @param startAngle the start angle * @param endAngle the end angle * @param anticlockwise is anti-clockwise */ @JsxFunction public void arc(final double x, final double y, final double radius, final double startAngle, final double endAngle, final boolean anticlockwise) { //empty } /** * Draws an arc. * @param x1 the x1 * @param y1 the y1 * @param x2 the x2 * @param y2 the y2 * @param radius the radius */ @JsxFunction public void arcTo(final double x1, final double y1, final double x2, final double y2, final double radius) { //empty } /** * Begins the subpaths. */ @JsxFunction public void beginPath() { //empty } /** * Draws a cubic Bzier curve. * @param cp1x the cp1x * @param cp1y the cp1y * @param cp2x the cp2x * @param cp2y the cp2y * @param x the x * @param y the y */ @JsxFunction public void bezierCurveTo(final double cp1x, final double cp1y, final double cp2x, final double cp2y, final double x, final double y) { //empty } /** * Clears the specified rectangular area. * @param x the x * @param y the y * @param w the width * @param h the height */ @JsxFunction public void clearRect(final double x, final double y, final double w, final double h) { //empty } /** * Creates a new clipping region. */ @JsxFunction public void clip() { //empty } /** * Closes the subpaths. */ @JsxFunction public void closePath() { //empty } /** * Creates a new, blank ImageData object with the specified dimensions. */ @JsxFunction public void createImageData() { //empty } /** * Creates linear gradient. * @param x0 the x0 * @param y0 the y0 * @param r0 the r0 * @param x1 the x1 * @param y1 the y1 * @param r1 the r1 */ @JsxFunction public void createLinearGradient(final double x0, final double y0, final double r0, final double x1, final Object y1, final Object r1) { //empty } /** * Creates a pattern. */ @JsxFunction public void createPattern() { //empty } /** * Creates a gradient. */ @JsxFunction public void createRadialGradient() { //empty } /** * Draws images onto the canvas. * * @param image an element to draw into the context * @param sx the X coordinate of the top left corner of the sub-rectangle of the source image * to draw into the destination context * @param sy the Y coordinate of the top left corner of the sub-rectangle of the source image * to draw into the destination context * @param sWidth the width of the sub-rectangle of the source image to draw into the destination context * @param sHeight the height of the sub-rectangle of the source image to draw into the destination context * @param dx the X coordinate in the destination canvas at which to place the top-left corner of the source image * @param dy the Y coordinate in the destination canvas at which to place the top-left corner of the source image * @param dWidth the width to draw the image in the destination canvas. This allows scaling of the drawn image * @param dHeight the height to draw the image in the destination canvas. This allows scaling of the drawn image */ @JsxFunction @SuppressWarnings("unused") public void drawImage(final Object image, final int sx, final int sy, final Object sWidth, final Object sHeight, final Object dx, final Object dy, final Object dWidth, final Object dHeight) { Integer dxI; Integer dyI; Integer dWidthI = null; Integer dHeightI = null; Integer sWidthI = null; Integer sHeightI = null; if (dx != Undefined.instance) { dxI = ((Number) dx).intValue(); dyI = ((Number) dy).intValue(); dWidthI = ((Number) dWidth).intValue(); dHeightI = ((Number) dHeight).intValue(); } else { dxI = sx; dyI = sy; } if (sWidth != Undefined.instance) { sWidthI = ((Number) sWidth).intValue(); sHeightI = ((Number) sHeight).intValue(); } try { if (image instanceof HTMLImageElement) { final ImageReader imageReader = ((HtmlImage) ((HTMLImageElement) image).getDomNodeOrDie()) .getImageReader(); if (imageReader.getNumImages(true) != 0) { final BufferedImage img = imageReader.read(0); graphics2D_.drawImage(img, dxI, dyI, null); } } } catch (final IOException ioe) { throw Context.throwAsScriptRuntimeEx(ioe); } } /** * Returns the Data URL. * * @param type an optional type * @return the dataURL */ public String toDataURL(String type) { try { if (type == null) { type = "png"; } return "data:" + type + ";base64," + encodeToString(image_, type); } catch (final IOException ioe) { throw Context.throwAsScriptRuntimeEx(ioe); } } private static String encodeToString(final BufferedImage image, final String type) throws IOException { try (final ByteArrayOutputStream bos = new ByteArrayOutputStream()) { ImageIO.write(image, type, bos); final byte[] imageBytes = bos.toByteArray(); return new String(new Base64().encode(imageBytes)); } } /** * Paints the specified ellipse. * @param x the x * @param y the y * @param radiusX the radiusX * @param radiusY the radiusY * @param rotation the rotation * @param startAngle the startAngle * @param endAngle the endAngle * @param anticlockwise the anticlockwise */ @JsxFunction(@WebBrowser(CHROME)) public void ellipse(final double x, final double y, final double radiusX, final double radiusY, final double rotation, final double startAngle, final double endAngle, final boolean anticlockwise) { //empty } /** * Fills the shape. */ @JsxFunction public void fill() { //empty } /** * Paints the specified rectangular area. * @param x the x * @param y the y * @param w the width * @param h the height */ @JsxFunction public void fillRect(final int x, final int y, final int w, final int h) { graphics2D_.fillRect(x, y, w, h); } /** * Dummy placeholder. */ @JsxFunction public void fillText() { //empty } /** * Returns the {@code ImageData} object. * @param sx x * @param sy y * @param sw width * @param sh height * @return the {@code ImageData} object */ @JsxFunction public ImageData getImageData(final int sx, final int sy, final int sw, final int sh) { final ImageData imageData = new ImageData(image_, sx, sy, sw, sh); imageData.setParentScope(getParentScope()); imageData.setPrototype(getPrototype(imageData.getClass())); return imageData; } /** * Dummy placeholder. */ @JsxFunction public void getLineDash() { //empty } /** * Dummy placeholder. */ @JsxFunction public void getLineData() { //empty } /** * Dummy placeholder. */ @JsxFunction public void isPointInPath() { //empty } /** * Connect the last point to the given point. * @param x the x * @param y the y */ @JsxFunction public void lineTo(final double x, final double y) { //empty } /** * Dummy placeholder. */ @JsxFunction public void measureText() { //empty } /** * Creates a new subpath. * @param x the x * @param y the y */ @JsxFunction public void moveTo(final double x, final double y) { //empty } /** * Dummy placeholder. */ @JsxFunction public void putImageData() { //empty } /** * Draws a quadratic Bzier curve. * @param controlPointX the x-coordinate of the control point * @param controlPointY the y-coordinate of the control point * @param endPointX the x-coordinate of the end point * @param endPointY the y-coordinate of the end point */ @JsxFunction public void quadraticCurveTo(final double controlPointX, final double controlPointY, final double endPointX, final double endPointY) { //empty } /** * Dummy placeholder. */ @JsxFunction public void rect() { //empty } /** * Pops state stack and restore state. */ @JsxFunction public void restore() { //empty } /** * Dummy placeholder. */ @JsxFunction public void rotate() { //empty } /** * Pushes state on state stack. */ @JsxFunction public void save() { //empty } /** * Changes the transformation matrix to apply a scaling transformation with the given characteristics. * @param x the scale factor in the horizontal direction * @param y the scale factor in the vertical direction */ @JsxFunction public void scale(final Object x, final Object y) { //empty } /** * Dummy placeholder. */ @JsxFunction public void setLineDash() { //empty } /** * Dummy placeholder. */ @JsxFunction public void setTransform() { //empty } /** * Calculates the strokes of all the subpaths of the current path. */ @JsxFunction public void stroke() { //empty } /** * Strokes the specified rectangular area. * @param x the x * @param y the y * @param w the width * @param h the height */ @JsxFunction public void strokeRect(final double x, final double y, final double w, final double h) { //empty } /** * Dummy placeholder. */ @JsxFunction public void strokeText() { //empty } /** * Dummy placeholder. */ @JsxFunction public void transform() { //empty } /** * Changes the transformation matrix to apply a translation transformation with the given characteristics. * @param x the translation distance in the horizontal direction * @param y the translation distance in the vertical direction */ @JsxFunction public void translate(final Object x, final Object y) { // empty } /** * Returns the associated {@link HTMLCanvasElement}. * @return the associated {@link HTMLCanvasElement} */ @JsxGetter public HTMLCanvasElement getCanvas() { return canvas_; } }