
We use web technologies in many aspects of our everyday lives and the web browser has become a significant vehicle for reading email, checking news headlines, watching video and more. The technologies and requirements of the web are constantly evolving while our dependency on the browser for delivering a myriad of content continues grow. As a result, a computing platform needs a powerful yet versatile web framework that supports the evolving web; one that can be leveraged by not only browsers but a host of other applications.
Apple's answer to that need is WebKit, a web content rendering engine which is the backbone of the Safari web browser. Designed as a reusable framework, it also powers a number of web-based technology on Mac OS X such as Dashboard widgets and Mail. In 2005, WebKit was released as an open source project,
allowing a wider developer community to both contribute to and benefit from WebKit's continuing
evolution.
One of the main benefits of an open source WebKit is allowing developers to download nightly browser builds from the WebKit Open Source Project page. Nightly builds allow you as a developer to prepare for changes before they wind up on your users' desktops.
This article describes how you can leverage WebKit nightly builds to determine how changes in the
framework may affect your web content, Dashboard widgets, or WebKit-based application in future
versions of Mac OS X.
Testing Your Content With Nightly WebKit
As you start working with WebKit nightly builds, you'll need to familiarize yourself with the WebKit Open Source Project page, found at http://www.webkit.org. Here you will find WebKit nightly builds, all of the WebKit sources, the "Surfin' Safari" blog (discussing current trends and happenings in the web content community), and more.
Downloading a WebKit nightly build onto your Mac is very easy. Go to http://nightly.webkit.org/ and click on the link to download a new build. A disk image will download to your Mac; open the disk image and drag WebKit.app to your Applications directory. Also included is Drosera, the JavaScript debugger for WebKit.app. We won't discuss Drosera in this article, but feel free to try it out on your own.
Windows users can now download and test nightly builds as well. This is a great way to stay current with developments in the WebKit engine after Safari 3 is released on both platforms.
Nightly WebKit vs. Safari
Once you download and install WebKit.app, you'll notice the gold-rimmed application icon. This makes the nightly build easily distinguishable from an official Safari release.

Figure 1: WebKit.app application icon
The WebKit.app nightly builds are completely self-contained and do not alter or replace the original WebKit framework on your system. This means that downloading and running a nightly build does not affect other WebKit-based applications (Safari, Dashboard, third party apps, etc). We will discuss using the nightly framework with your own applications later in this article.
As a convenience, WebKit.app checks to see if a newer build is available for download at launch time.

Figure 2: WebKit.app start page
Once you have an up-to-date WebKit.app, you can start experimenting with its new engine. It is important to remember that Safari is just a client of WebKit; it's the WebKit engine which performs the heavy lifting of processing CSS, running JavaScript code, and rendering the portions of the web page that are presented to the user. There are plenty of other Mac OS X technologies that rely on WebKit: Dashboard, Mail, and Help Viewer to name a few. This means that
changes to WebKit may affect not only web page developers, but widget and application developers as
well. The nightly builds provide a valuable opportunity to respond to changes in WebKit—be
they feature enhancements, regressions or implementation modifications—before a new version
officially makes its way to your customers running Mac OS X.
Canvas Standardization in Nightly WebKit
The canvas object is one example of an element that has gone through significant changes visible in nightly WebKit builds. Apple introduced the canvas element in the WebKit framework released with Safari 2.0 as a way to dynamically draw images and vector graphics on a web page. It has since been included in the WHATWG HTML 5 specification and adopted by browsers including Firefox and Opera. With Safari now on iPhone, iPod touch and Windows, canvas has become available to a much wider audience.
The proliferation of canvas support to multiple browsers underscores the importance of this standardization process. As the specification solidified, a few significant changes were made to the canvas HTML tag and accompanying JavaScript API:
- An explicit close tag,
</canvas>, is required.
- Width and height attributes are required in the HTML markup.
- Differences between HTML width/height and CSS width/height result in a scale.
- A call to
beginPath is required to clear the context state.
Let's start with the first case. The original canvas element allowed use of a self-closing HTML tag:
<canvas style='width:172; height:172' width='172' height='172' id='myCanvas'/>
To match the WHATWG specification, current builds of WebKit require canvas elements to include explicit close tags; implicitly- or explicitly-closed empty canvas elements consisting of only start tags are no longer accepted. An explicit, separate close tag allows for fallback content to be presented to users using browsers without a canvas implementation. For example:
<canvas style='width:172; height:172' width='172' height='172' id='myCanvas'>
<div id='errorDiv'>Your browser does not support canvas</div>
</canvas>
To understand what this means to developers, let's look at a simple example. The following canvas code draws one vertical line, clears the area, then draws a second line.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Canvas Path Test</title>
<script type='text/javascript'>
function main() {
var context = document.getElementById("myCanvas").getContext("2d");
context.lineWidth = 10.0;
context.lineCap = "round";
context.beginPath();
// Draw a bounds rect (default color is black)
context.strokeRect(0, 0, 300, 300);
context.strokeStyle = "#808080";
// Draw a vertical line
context.moveTo(100, 100);
context.lineTo(100, 200);
context.stroke();
// clear the area inside our drawn boundary
context.clearRect(50, 50, 200, 200);
// Draw another line
context.moveTo(200, 100);
context.lineTo(200, 200);
context.stroke();
}
</script>
</head>
<body onload='main();'>
<canvas style='width:300px;height:300px' id='myCanvas'/>
<div style='position:absolute; top:320px;'>This text appears below the canvas</div>
</body>
</html>
Figure 3 shows what this code produces in Safari 2.

Figure 3: Seemingly innocent canvas behavior
However, this same code produces much different results using WebKit.app.

Figure 4: Old canvas code in new WebKit
There are a number of problems here. First, notice that the text below the canvas no longer appears. This is because the code uses a self-closing canvas tag instead of a separate close tag. WebKit.app acts as if the tag was never closed. As a result, the text element is not parsed or rendered.
The first step, then, is to add a proper close tag to our HTML, as explained earlier.
<body onload='main();'>
<canvas style='width:300px;height:300px' id='myCanvas'></canvas>
<div style='position:absolute; top:320px;'>This text appears below the canvas</div>
</body>
This change allows the markup following the canvas to be recognized again.
NOTE: It is worth mentioning that a similar change has been made to <script> tags in nightly WebKit builds; non-standard self-closing <script/> tags are no longer recognized and any content following them is not rendered. Accompanying </script> tags are now required.

Figure 5: Improved canvas markup
However, we are still far off from what we see in Safari 2. The content now appears, but appears vertically stretched. This is because the new specification handles sizing of the canvas differently in two key ways.
First, the specification now enforces a default canvas size of 300 by 150 if no height and with attributes are included in the opening tag. Note the original example does not include those attributes.
Second, the specification requires that if the CSS dimensions differ from the content dimensions, a scale should be applied to all operations by the browser. This scale is applied by dividing the style dimension by the content dimension.
Let's see what this means: Since no content size was set, the content size now defaults to 300 by 150. The inline style was set to 300 by 300.
| |
Style |
Content |
Scale |
| Width |
300 |
300 |
1.0 |
| Height |
300 |
150 |
2.0 |
With a default height of 150 and a style height of 300, the canvas now has a y-axis scale of 2.0. The default width of 300 matches the style. This explains why the canvas is stretched vertically but not horizontally.
We solve this problem by including width and height attributes that match the inline style.
<canvas style='width:300px;height:300px' width='300' height='300' id='myCanvas'></canvas>

Figure 6: Properly-sized canvas element
An explicit width and height allow WebKit.app to render the canvas properly. If we need to change the size of the canvas later, we should change the content attributes and set the style to match if we do not want a scale to be applied when resizing:
var myCanvas = document.getElementById("myCanvas");
// resize the canvas to a width of 200px
myCanvas.width = 200;
// set the style to match the content, otherwise a scale will occur
myCanvas.style.width = myCanvas.width + "px";
// redraw the canvas...
You're almost there. Notice that WebKit.app is showing both lines, whereas Safari 2 only shows the second line drawn. This was another standardization change, this time made to the JavaScript object: the canvas no longer clears its path after each call to stroke(). As a result, the second stroke() call draws both lines instead of just the second line. To solve this problem and only draw the second line, call beginPath to explicitly clear the path after the first line is drawn.
// Draw a vertical line
context.moveTo(100, 100);
context.lineTo(100, 200);
context.stroke();
// clear the area inside our drawn boundary
context.clearRect(50, 50, 200, 200);
// Call beginPath to clear existing state
context.beginPath();
// Draw another line
context.moveTo(200, 100);
context.lineTo(200, 200);
context.stroke();
With these changes, the nightly build matches Safari 2.

Figure 7: Standard-compliant canvas code
Note that the new code still works in the official Safari release; the behavior between Safari, WebKit.app, and even Firefox are now identical whereas they had previously all been different. Thanks to the standardization process, cross-browser canvas element usage should be more predictable moving forward. So, to prepare for the official canvas specification:
- Add a closing tag to your canvas
- Include height and width attributes (as opposed to style)
- Call
beginPath to clear the path state
This is an example of a change that potentially affects any variety of web-based content, including Dashboard widgets. The availability of the nightly builds allows you to anticipate and adapt to these changes before they are officially integrated into Mac OS X.
Testing Your Application With Nightly WebKit
Once again, WebKit is not just Safari—it's a browser engine that can be used by any Mac OS X application. Developers utilizing it should make sure the newest versions work as expected with their applications. Full source code for the WebKit framework is available for download and customization, but this might be overkill for projects which simply use the untouched framework.
Luckily, testing your application against a nightly build of the WebKit framework is very easy. All you need to do is create a custom executable in Xcode and tell it to use the framework inside WebKit.app instead of the standard system framework. Let's take a look at this using the MiniBrowser sample, located in /Developer/Examples/WebKit/.
- Choose Project: New Custom Executable...
- Enter a name (e.g. MiniBrowserNightly)
- Next to Executable Path, click Choose... and navigate to MiniBrowser.app in your build directory
- Click Finish
An info window for your new custom executable appears. This is where you set environment variables to make your built project use the nightly WebKit framework instead of the copy in /System/Library/Frameworks.
- Select the Arguments tab in the info window
- Under the "Variables to be set in the environment" pane, click the plus button and set a variable called
DYLD_FRAMEWORK_PATH to the Resources directory of your nightly WebKit application bundle (e.g. /Applications/WebKit.app/Contents/Resources/
- Add a second variable,
WEBKIT_UNSET_DYLD_FRAMEWORK_PATH, with a value of YES

Figure 8: Custom executable environment variables in Xcode
Testing MiniBrowser with a WebKit nightly build is as simple as a configuration change. Just choose Project: Set Active Executable: MiniBrowserNightly, and run your project (or build and run). You can try our earlier "bad" canvas example to confirm you are using the nightly WebKit.
This is all you need to test the latest WebKit.framework with your WebKit-based application: no source changes, no recompile.
Conclusion
The WebKit Open Source Project allows developers to track the progress of this essential component of Mac OS X and Safari on multiple computing platforms and devices. Web developers, Dashboard developers, and WebKit application developers now have advance access to new features and changes in the browser engine they depend on. Nightly builds are easy to get, easy to test, and easy to integrate into your own application. Check one out today and be ready for the future!
For More Information
Posted: 2007-09-21
|