Saturday, December 25, 2010

Draw Text and Shadows with GWTCanvas

Overview
This post will describe how to draw text and shadows with GWTCanvas.

Example render of the HTML5Canvas widget (click image to enlarge):


Introduction
I started experimenting with HTML5 and GWT for a the user interface of a pet project I've been working on the last 2 years or so. At first I was using SVG through the Tatami GWT library, but decided to investigate the possibility of using the canvas.

Unfortunately the standard GWT doesn't have widgets for interfacing with the HTML 5 canvas. The gwt-incubator project does have a GWTCanvas widget with basic support for the HTML5 canvas. Since the poor support of the <canvas> element in Internet Explorer, GWT emulates most of this. I figure this is the reason not all of the canvas API is provided via the GWTCanvas widget.

One of the big missing features is the ability to draw text. One day, when Internet Explorer will support all of the canvas element, I'm sure the GWTCanvas will become much more functional.

I am not targeting IE though. Being perfectly happy with Firefox and Google Chrome as a client, I want to be able to leverage all the canvas element's features, like shadows and drawing text. One day when IE implements it everything will hopefully fall in place. Not provided by the GWTCanvas I decided to extend it and provide these features.

If you really need support for drawing text on Internet Explorer as well, you could possibly use the SWTB Canvas Font extension.

Note that HTML5Canvas isn't an extension in the sense of extending the GWTCanvas widget class. Due  to the GWTCanvas class not exposing the canvas context JavaScriptObject, I had to copy the classes completely. I do use some of the classes that GWTCanvas depends on, and for this reason the gwt-incubator JAR is necessary on the classpath as well.  For convenience, I do supply all the necessary JARs on the SourceForge project.

This extension was based on the version 20101117-r1766 of the gwt-incubator library for GWT 2.1.0.

How to add the HTML5Canvas extension to your project
  1. Downloads the JARs at: https://sourceforge.net/projects/html5canvas/. Get both the gwt-incubator and html5canvas JAR.
  2. Add these JARs to your classpath.
  3. Add the following to your .gwt.xml file:
    <inherits name="com.blogspot.qbeukes.gwt.html5canvas.HTML5Canvas"/>
  4. You're ready to go!
Using HTML5Canvas
Creating the Widget
You need to create an instance of com.blogspot.qbeukes.gwt.html5canvas.client.HTML5Canvas and add it to your display as you will add any other widget.

Shadows
Shadows are configured with these methods:
public void setShadowBlur(double blur);
public void setShadowColor(Color color);
public void setShadowOffset(double x, double y);
public void removeShadow();

Then you can just stroke/fill and whatever you make visible will have a shadow.

Example:
canvas.saveContext();

canvas.setShadowBlur(5);
canvas.setShadowOffset(4, 4);
canvas.setShadowColor(Color.BLACK);
canvas.setFillStyle(Color.RED);
canvas.fillRect(10, 20, 50, 50);
canvas.removeShadow();

canvas.setStrokeStyle(Color.BLACK);
canvas.strokeRect(10, 20, 50, 50);

canvas.restoreContext();

Text
To draw text you first need to create an instance of com.blogspot.qbeukes.gwt.html5canvas.client.Font. Through this class you can configure font family, size, variant, weight and all the CSS font properties available in HTML.

From here you can use HTML5Canvas.setFont(Font) to configure it, and then use these methods to draw/configure text:
public void fillText(String text, double x, double y);
public void strokeText(String text, double x, double y);
public double getTextWidth(String text);
public void setTextBaseline(String textBaseline);
public void setTextAlign(String textAlign);

Font colors are configured with fill and stroke style, depending on which method you use to draw the font.

Composite Operations
Composite operation support is already available in GWTCanvas through setGlobalCompositeOperation(String), though there are only constants for destination-over and source-over.

HTML5Canvas adds a new method, setGlobalCompositeOperation(com.blogspot.qbeukes.gwt.html5canvas.client.CompositeOp) and the CompositeOp enum used in the argument of this new method.

The CompositeOp enum contains the following constants:
CompositeOp.SOURCE_ATOP
CompositeOp.SOURCE_IN
CompositeOp.SOURCE_OUT
CompositeOp.SOURCE_OVER
CompositeOp.DESTINATION_ATOP
CompositeOp.DESTINATION_IN
CompositeOp.DESTINATION_OUT
CompositeOp.DESTINATION_OVER
CompositeOp.LIGHTER
CompositeOp.COPY
CompositeOp.XOR

Demo/Examples
For demo/examples, see com/blogspot/qbeukes/gwt/html5canvas/demo/HTML5CanvasDemo.java.

This source file can be found
  1. Inside the HTML5Canvas JAR, or 
  2. Through Subversion from the SourceForge project under trunk/src/.
You can also download the WAR from the SourceForge project and deploy this to a servlet container like Tomcat.

Conclusion
That's it. Enjoy.

No comments: