Info

Tech entrepreneur, executive, and investor; father of eight children; Googler.

Archive for

One of the disadvantages of writing a blog post on little sleep late at night in a hotel room while watching a movie and talking with Dion and doing your email is that you inevitably forget to write something you meant to.

In this case, one of the big drivers for writing the previous Bespin and Canvas post was to discuss accessibility–which I then neglected entirely to mention. Let me rectify that here and add a few other miscellaneous bits.

Accessibility

Rendering all of our content to a giant bitmap is obviously not the best way to integrate with all kinds of technologies designed to make content more accessible in various ways. But getting past that initial observation, we’re actually really interested in finding ways to make Bespin very accessible.

One of our initial ideas is to embed semantic content inside of the <canvas> element itself, as in:

<canvas>
  The content inside the Bespin editor
  could be embedded inside here as text nodes
</canvas>

It might not be expensive (in UI latency terms) to keep these text nodes synchronized with the canvas editor since the UI thread doesn’t need to re-render anything as a result of the constant updates. If this approach were to incur a performance penalty, Bespin could have an “accessibility mode” that would optionally turn this on.

Bespin Dashboard

Bespin Dashboard

The Bespin dashboard also uses canvas, but for components instead of just text. We’re actually thinking of killing two birds with this one and having the hierarchy of the components defined inside of the <canvas> element:

<canvas>
  <splitPanel>
    <list/>
    <horizontalTree/>
  </splitPanel>
</canvas>

We could then build the UI using this hierarchy rather than by using the entirely programmatic approach we have in place now:

// this is pseudo-code not pulled directly from Bespin, but
// Bespin's dashboard code looks similar
var splitPanel = new SplitPanel();
var list = new List();
var tree = new HorizontalTree();
splitPanel.add([ list, tree]);
...

You would style and layout these components using separate artifacts (CSS and a layout-specific artifact).

We’ll talk more in a future blog post about this concept of using canvas to render components; it’s really more about supplementing DOM-rendered components with canvas-rendered components and laying out the combination with JavaScript (rather than CSS / HTML)–this is what we briefly mentioned as “Thunderhead” in the announcement video.

An advantage to this approach for accessibility is that we can provide a clean, fully-semantic hierarchy of the content, rather than status quo of HTML which runs the spectrum from style-and-content-mashed-together-seamlessly on one end to almost-pure-semantic-content-with-a-few-compromises-to-deal-with-CSS-realities on the other.

Let me again emphasize that Thunderhead is an experiment at what this kind of thing would look like; we’re not sure if we like it and we may scrap it entirely at some future point.

SVG?

We’re frequently asked why we didn’t use SVG for the editor. To be honest, the biggest reason is that I have a lot of experience creating custom components with Java2D, and Java2D strongly resembles the canvas API. It was pretty natural to start hacking away with canvas and JS.

But there are a few reasons we felt good about going down that road to begin with. First, based on experimenting with DOM rendering, we felt we had good reason to suspect that SVG wouldn’t perform as quickly as the canvas implementation since SVG has its own DOM API and thus is likely to mirror all of the performance issues to be had with HTML’s DOM.

On top of that fundamental concern, we had another: while it’s straight-forward to implement our own painting optimizations in canvas (and we have), with SVG it’s much more subtle and involves understanding the implementation details of SVG run-times and whatever optimizations have been implemented under their covers (again, the same as with HTML DOM performance optimization).

Also, as a fairly large specification, we were concerned about compatibility headaches as differing subsets of SVG are implemented in the browsers that support it. We didn’t have the energy to fight DOM compatibility issues during the day and SVG compatibility headaches at night.

Having said that, we’d love to see an SVG version of the Bespin editor emerge at some point and compare its performance and codebases. There’s certainly a good chunk of JS code that could go away if an SVG version worked out.

Stand-alone Editor?

We’ve also been asked whether we’d like to make it easy for folks to embed Bespin’s canvas editor in their own non-Bespin projects. Absolutely we do. Bespin will eventually spin out three projects:

  1. The Bespin project: an on-line code editor (i.e., the project we’ve currently announced)
  2. Thunderhead: a canvas/JS GUI toolkit
  3. (To Be Named Editor): a stand-alone canvas editor that you can embed

To make it seem less like I’m making this up just now, here’s what the Thunderhead logo looks like:

Thunderhead

Canvas versus Firefox

Some folks have also wondered why we didn’t just enhance Firefox to do the things that we achieved by using canvas and JavaScript. The answer to that is simple: we’re not interested in making Bespin only run on Firefox. We want as broad an audience as possible to use it.

However, we’re already talking with standards folks and browser folks about how best to pull some of these ideas back into the browsers. This isn’t canvas versus the browser, it’s about using canvas to experiment with new features ahead of the browser, and applying those “learnings” (is that really a word? WTF) back to the browsers.

More to come soon, thanks for reading.

Bespin

It’s been thrilling to finally release Bespin to the world. There’s nothing quite like seeing feedback start pouring in via IRC, blog comments, Twitter, and email within minutes of pushing “Post” on the first announcement blog entry. I’m very grateful to everyone who has taken some time to engage with us in any of the various media out there. We’ve also seen some interesting community efforts at extending Bespin; check out our blog post on the Labs website for details.

Culling through everything, it’s clear that a few aspects of the project are controversial. I’d like to address one of them: our choice of canvas as the rendering engine for the editor.

Bespin and Canvas

Bespin takes advantage of a relatively new feature of browsers to power its text editor: the <canvas> element. Canvas gives developers something the intriguing ability to render arbitrary two-dimensional graphics in a web page; it’s basically an <img> element you can draw into with JavaScript commands. The API looks something like this:

// all drawing performed via the context
var ctx = document.getElementById("canvasId").getContext("2d");

ctx.fillStyle = "black";  // accepts same values as CSS "background" property

ctx.fillRect(0, 0, 50, 50); // draws a black 50x50 rectange in the canvas

Canvas is available in the currently released versions of Safari, Opera, Firefox, and Chrome; it has been a part of the HTML 5 draft specification for a long time. It is not available in Internet Explorer.

Bespin builds on this API to recreate a text editor from scratch. That’s right; rather than use the native facilities of every modern operating system that give you word processing features for free, Bespin rolls them from scratch, including such basic constructs as a blinking cursor and text selection.

The Bespin Editor

The Bespin Editor

One of the the features we didn’t have to re-implement is text rendering; the HTML 5 specification includes an API to render text on a canvas. Unfortunately, this portion of the canvas API has only been implemented by Firefox, though it’s already in WebKit nightly builds (and thus will very likely be in a future version of Safari) and Chromium nightlies (from which Chrome versions are derived). We expect Opera will soon as well.

But Does It Scale?

We weren’t actually sure this would work when we set out to do it. You wouldn’t think a JavaScript interpreter in a browser could render enough frames on a large, modern 32-bit image display to make the experience anything close to what you get effortlessly in Notepad on Windows XP running on 10-year-old hardware.

To be sure, for some users, the performance does indeed suck–we’re looking into exactly why (it appears that certain video drivers cause performance problems on Linux; Google Chrome’s multi-process architecture appears to slow down performance on that browser). The interesting thing is that for large classes of users, performance is really, really good. There’s a lot to say about topic; we’ll touch on that more in a future blog post.

Why?

The first time we demoed Bespin to someone who understand these implementation details, the reaction was “Wow, you’re crazy!” followed by “That’s really cool.” Pretty much everyone else I’ve spoken with has the same first reaction (the crazy bit) but the follow-up is not always positive (ranging from the aforementioned to “WTF!?”).

Surely there’s a higher-level abstraction we could have built on? Something above pixel painting?

Well, let’s get one thing out of the way first-up: there may very well be a more effective way to do what we’ve done than with canvas. I’m not saying this is the best way to do it; I just want to explain why we did it.

Control, Control, We Must Have Control

One of our goals with Bespin is to be able to (at some point in the future) deliver a fantastically compelling user experience for editing code on the Web. We don’t want Bespin to be the editor you use when you can’t get to your desktop; we want it to be your editor of choice in any context.

It turns out that’s a tall order. Some users like word-wrapping; some don’t. Some users actually like column selection modes while other (more sane) users like line-oriented selection (I kid, I kid). Developers are notoriously finicky with their tools–especially their code editor–and we didn’t want to re-educate the world on how our editor worked; we want to make Bespin adaptable to as wide an audience as we could.

We felt that if we built Bespin on something like <textarea> or the “content editable” feature of HTML, we’d have a built-in set of limitations over which we’d have very little or no control.

The Alternatives

To build on the last paragraph, we considered three different alternatives to canvas:

  1. textarea
  2. contentEditable
  3. “line blocks”

The “control” argument above is one reason we dismissed textarea and contentEditable; further, we’ve seen a large number of other web editor implementations based on these approaches and based on playing with those and by the many horror stories floating around the Web from their authors, we were concerned that we couldn’t overcome performance and compatibility problems, especially when editing large files.

Line Blocks

“Line blocks” are a different story. What if we had a bunch of <div> elements stacked vertically and treated each one as a rendering surface for a line of text in the document being edited? We played with that approach a bit but couldn’t get as much performance out of it as we could with canvas, especially for wide files (>80 columns).

Compatibility

We’ve taken some flak for claiming that Bespin is based on “Open Web technologies” but only supporting Firefox and WebKit nightly. Earlier in this post, I explained the state of canvas support in the browsers and how we’re hopeful that our canvas approach will work in future versions of Chrome, Safari, and Opera.

However, we have a plan in case browsers don’t implement the proper text rendering APIs: bitmap font rendering. By pre-rendering fonts into images, we can then render the images on the canvas. There are a number of proof-of-concept implementations floating around that demonstrate this concept (though unlike some, we wouldn’t render the fonts as vectors–there’s no way it would perform to our needs).

What about Internet Explorer? It’s hard to say what the future of canvas support is for IE; it certainly isn’t coming in IE8. However, there are a number of projects that emulate canvas by mapping it to VML (an abandoned IE proprietary rendering technology), Flash, and Silverlight. So far, none of these bridges offers adequate performance for us to seriously considering supporting it. We’re aware of promising developments in this area and we’ll experiment with IE support as these technologies evolve.

Mobile Support: iPhone, Android, Fennec, and More

We’re also very excited to get Bespin working on mobile devices with fully-featured browsers. The iPhone’s browser–”mobile Safari”–does support canvas, but does not yet have the text rendering APIs. We may implement the aforementioned bitmap font rendering just to get on the iPhone. We are also looking at other mobile platforms, such as Android, Fennec, Palm, and so forth.

How cool would it be to change your code and redeploy it from the beach?

Obviously, it will take some interface changes for Bespin to be usable on a mobile device. We have some ideas here and we look forward to working with the community on developing the concepts further.

What do you think?

What do you think of our use of canvas in Bespin’s editor?

Note: I realized the morning after that I had omitted some of what I meant to include in this post; I’ve retroactively renamed this post “Part 1” and added a “Part 2”.