The Good Life... a weblog about life, technology, and the Opera web browser

Acid3: 100/100 and Pixel Perfect

Two days ago, we announced we had achieved 100/100 on the DOM portion of the Acid3 test. Later that evening, a bug was found in the Acid3 test itself. The bug was fixed and the WebKit team announced that they had achieved 100/100 on the DOM portion of the test and they had pixel-perfect rendering, making them the first to achieve two of the three pass conditions (congrats on that, by the way!).

Today, we'd like to announce the same. We have achieved 100/100 with pixel perfect rendering:

Screenshot of the Acid3 test from Opera's latest internal builds

This screenshot is copyright Opera Software ASA and released under the Creative Commons Attribution-ShareAlike 3.0 License.

Windows and Linux users may test this out themselves by downloading the GOGI build available from the Opera Labs. A note about these builds: GOGI, short for Generic Opera Graphics Interface, is a tool our Core team uses internally to develop our cross-platform/cross-project code. It has a very simple UI, which is nothing at all like Opera for Desktop. It is in no way meant to replace Opera for Desktop and we don't expect to duplicate any GOGI features in Opera for Desktop. It also lacks some security features, and thus we recommend that it not be used for regular surfing. Furthermore, please don't file bug reports about problems you find in GOGI.

Now, WebKit and Opera have reached the same point and have the same challenge: optimize enough to run test 26 in 33ms.

The Acid3 Test

At the beginning of March, the Web Standards Project (WaSP) released Acid3, a web standards spot-checking test. As with Acid2, the goal of the test is to improve interoperability between web browsers. The Acid3 test consists of 100 DOM sub-tests, which assess a browser's support for DOM, CSS, SVG, and ECMAscript, as well as some rendering tests. To pass the test, a browser must render the test pixel for pixel identical to the reference rendering, pass all 100 DOM tests, and animate the test smoothly. So far, Opera is the only browser to pass all 100 DOM tests (more on that in a bit). Information about the pass rates for browsers is available in Wikipedia's excellent article about Acid3.

While browser vendors implement the same web standards, their implementations are sometimes incompatible due to bugs, different interpretations of the standards, or missing functionality. Incompatible implementations increase the development time and decrease the innovation of web sites/applications. Thus, the WaSP Acid tests establish a compatibility baseline that web developers can count on during development. That is, once browser vendors pass the tests.

As with the Acid2 test, the Acid3 test should not be viewed as a race. It's all about improving interoperability and making the Web a better place. If only one or two browsers pass the test, the test isn't a success and the Web can't improve. It's important that all major browsers (Firefox, Internet Explorer, Opera, and Safari) pass the test. The Acid2 test was released in April 2005, yet three years later only final releases of Opera and Safari pass it. That means web developers still can't rely on the functionality in Acid2 as a baseline. It'll probably be at least two or three years before the functionality tested it Acid3 can be used as a baseline.

Opera's Progress on Acid3

At Opera, we rely on web standards to allow us to render live web sites correctly. Interoperability allows us to use a different rendering engine, yet render web pages the same as other browsers. That's one of the reasons we've put a lot of focus on the Acid3 test since it was released:

  • Opera's latest final public release, 9.26, scores 46/100 on the test and has some significant layout problems
  • The initial alpha of Kestrel, released in September 2007, scores 58/100 on the test and has some small layout problems. At that point, we had not done fixes specifically for the test, which is a testament to the rendering engine improvements in Kestrel
  • Our latest snapshot release scores 77/100 and has some small layout problems
  • Our latest internal build (screenshot below) scores 100/100 and renders the test almost perfectly! We have some work to do still, but we expect to have that taking care of shortly. UPDATE (2007-03-27): a bug was found in the Acid3 test, which may affect our pass rate

Screenshot of the Acid3 test from Opera's latest internal builds

This screenshot (and the screenshot it links to) are copyright Opera Software ASA and released under the Creative Commons Attribution-ShareAlike 3.0 License.

This is the first time a screenshot of GOGI, our internal testing platform, has been released publicly. Core developers and testers use GOGI for their development, so they have a platform-independent setup. Also, Core testers do regression testing in GOGI before Core fixes are released to the Desktop Team build. That said, Kestrel may not pass the Acid3 test, even if internal builds do. Some of the internal fixes are experimental and they need regression testing before they can become part of a Desktop release. We hope to have a public test build within the next couple weeks that passes the test.

Routine Body Scans

I'm looking forward to the day when we'll have routine body scans. If you're exposed to a lot of science fiction, as I am, you've probably seen what I'm referring to: some sort of bed where you lie down and you get scanned. The doctors know immediately if there's anything wrong with you. It's simple, painless, and just a regular part of medical care. Nowadays, it seems like so much can be lurking within you without showing any outward symptoms. If we could all go to the doctor and get a body scan every six months or so, we'd find problems sooner (at a more treatable stage) and get more accurate diagnoses.

Sure, there are a some scanning technologies today, such as MRI or CT, but they're much more limited than I have in mind. I've had two MRIs: one on my jaw and one on my wrist. In both cases, I had to stay very still for several minutes while a specific area was targeted. MRIs only show slices of certain parts of our bodies, so I imagine a full body MRI would take hours. Not fun. CT, also known as CAT scans, uses x-rays, so I imagine any large-scale and regular scanning would have adverse effects.

I actually found my first MRI quite relaxing. If you haven't had an MRI, there's a lot of noise involved. The noise is something like the sound of wood blocks being knocked together continuously. For whatever reason, I found the noise very soothing and I almost fell asleep. The MRI on my wrist might have been equally relaxing, but I was in an uncomfortable position.

In any case, I hope we'll see such technology in my life time. That, and teleporters.

Behind My Site Relaunch

As part of my site relaunch, I did some major behind the scenes work on the software used to run this site. I had been using Drupal 4.6, which was released in April 2005. Since then, Drupal has had three major releases, the most recent in February. In addition to using the core Drupal software, I use several third-party add-ons (called modules). Since modules usually take some time to be compatible with new core releases, I decided to base my site on Drupal 5, which works with a large number of modules.

When I first launched my site using Drupal, I used the core blog module, since I figured it made sense to blog using blog module (a fair conclusion). However, since I was the only user blogging, I found the extra bits of UI added by the blog module got in the way rather than helped. As part of the upgrade and based on the Dag Wieërs' advice, I decided to ditch the blog module and use the generic story module. It's been a seamless transition so far.

I enjoy the dialogue that sometimes occurs in post comments, so I wanted to see if upgrading could improve the usability of comments. Previously, I allowed site visitors to register at the site, which gave them a couple additional benefits, such as e-mail notification of new comments and posts. Unfortunately, the vast majority of these registrations were used to post spam and very few registered users actually used the e-mail notification, so I decided to disallow new registrations and delete all old registrations. The site now automatically remembers commenter information and I added the ability for users to receive e-mail notification of new comments to a specific post if they've commented on it. Additionally, I added several new RSS feeds: all comments, comments to specific categories, and comments to specific posts.

As if that weren't enough, I also changed the way comment subjects work. By default, Drupal will take a chunk of the comment body and use it as the comment subject if a commenter doesn't fill in a subject. In practice, this leads to a bunch of duplicate text between the comment subjects and bodies. Instead, my site will use the post title as the default comment subject. The alternative was disabling comment subjects, but some of the other functionality I added requires comment subjects, so this ended up being a good compromise.

Spam is one of the big concerns for anyone allowing comments to their site. There's a great third-party spam module for Drupal that I used on my old site. That caught a large amount of spam, but I'd like to prevent spam from being posted in the first place. So, in addition to the spam module, I decided to require commenters to enter a CAPTCHA. Instead of using the CAPTCHA module's default arithmetic CAPTCHA, I decided to use the reCAPTCHA service. reCAPTCHA, a project of Carnegie Mellon University, uses words that couldn't be understood by OCR software when books were scanned. So, the CAPTCHAs that are solved on my site are helping to archive books digitally. It's a really neat idea and I'm glad I can be a part of the project. As an additional measure, I'm using the commentcloser module to stop comments on all posts a set amount of time from their publication.

I decided the relaunch was a good time to give posts more recognizable URLs, rather than just using "/node/1234". I wanted the URLs to be as meaningful as possible, so using the pathauto module, they are now title- and date-based, i.e. "archive/2008/03/02/title". Many sites that use this format don't have true path hierarchies for the URL, meaning that visiting "archive/2008/03/02/" would return a "Page Not Found" error. I'm a big fan of path hierarchies, so I decided to use the archive module to help out. By default, the archive module uses the "all" keyword in the URL to determine which types of content to display. Since I only have one type of content I want displayed in the archives, I hacked the archive module to remove the keyword handling, so it automatically handles the path hierarchies for me. Now post URLs are meaningful and allow easy access to archives.

Of course, I would be committing the cardinal sin of web sites if I changed all my URLs without also making them accessible from the old URL. Drupal has built-in functionality for this using path aliases. If I used this functionality, my content would available both at the old and the new. Unfortunately, Google dislikes such duplicate content. Global redirect to the rescue! This module uses redirects to forward the reader to the new URL rather than allowing content to be accessible at both URLs.

Another new addition to the site is a copyright. Previously, my site didn't indicate how the content was copyrighted. Though, I never saw evidence of misuse, I figured I would rather be safe than sorry.

Here's a list of the modules I found essential for this site; these modules should be seriously considered for any Drupal-based blog:

  • archive: date-based post archives
  • captcha: anti-spam measure: require users to enter a captcha to post a comment
  • comment_info: remember anonymous commenter information
  • comment_notify: e-mail notification of new comments to previous commenters
  • comment_subject: default comment subjects based on node title
  • commentcloser: anti-spam measure: close comments after a set period of time
  • commentmail: e-mail notification about new comments for site administrators
  • commentrss: provide various RSS feeds for comments
  • copyright: add copyright notices
  • elf: add an image indicating off-site links in posts
  • globalredirect: uses 301 redirects to stop duplicate content from arising when path module is enabled
  • pathauto: creates memorable URLs
  • pathfilter: filter for referencing internal paths, e.g. previous posts
  • quote: node and comment quoting functionality
  • recaptcha: anti-spam measure: use the reCAPTCHA service for CAPTCHAs
  • spam: anti-spam measure: apply Bayesian filtering to submitted comments
  • xmlsitemap: provide a sitemap for search engine spiders to improve search engine ranking

I'd be happy to give additional information about my site setup as requested.

Back in the Picture

Back in college, I took photography courses that opened my eyes to the world beyond point-and-shoot cameras. For the courses, I bought a Minolta SRT-101 from my uncle. The SRT-101 is a fully manual camera: the only thing automatic about it is the light meter. I used to take roll after roll of film and develop them in the school's dark room. I still used it after college, but without having a dark room readily available, I didn't have as much freedom with my prints. I had some bad experiences getting film developed and I've since shelved my SRT-101. That's really unfortunate because it's a great camera for shooting black and white images. The pictures I took with it are still some of my favorites.

After graduation, my grandparents bought me a Canon Powershot A70 digital point-and-shoot camera, which was one of the best digital point-and-shoot cameras available at the time. Most digital point-and-shoot cameras are almost fully automatic, but the A70 allowed me to at least change the aperture setting. Since then, I've taken thousands of photos and my A70 keeps right on shooting vibrant and beautiful photos. Despite the camera's advanced technology and photo quality, I found myself missing the versatility and hands-on experience of SLR cameras.

Over the past couple of years, I've found my interest in using the A70 wane. It's been a tough time because I really enjoy photography, but I often found myself frustrated at not being able to get the right depth of field or focus on the subject of my photo instead of whatever the camera chose. I started to feel like all my pictures looked the same and I blamed it on the A70's limitations. To be fair, I know at least part of the problem was my lack of creativity. I'm sure I could do more with the A70, but my mind has subconsciously been made up that it's holding back my potential.

At the beginning of February, I decided that was time to take the digital SLR plunge. After quite a lot of research, I finally settled on the Canon EOS 40D with a Canon EF-S 17-55mm f/2.8 IS USM lens. Since the lens was backordered, I also ended up getting a Canon EF 50mm f/1.4 USM lens. Both are fantastic lens, with the former offering super wide-angle shots and the latter offering extremely shallow depth of field.

I haven't been able to get out as much as I would like, but I am beyond happy with my purchase. I've found my interest renewed in going out simply to take photographs. I again pick up my camera to photograph something mundane that can be given new life in a photograph. I've found myself posing inanimate objects to get the best image composition. It's such a fantastic feeling to have something I enjoy so much no longer frustrating me.

I still have a lot to learn. The 40D is a very advanced camera with tons of features and loads of configurability. Not just that, but I have a lot to learn about different techniques. I need to learn about panning. I need to learn how to better take advantage of the depth of field and wide angle possibilities of my lenses. I'm sure I'll have enough to experiment with to last me years. And I am so happy to have so much to learn!

Funny Mater

Picture of Sara EllenSara Ellen is now twenty-six and a half months old. Compared to the first two years of her life, the development she's going through now is much more subtle. This week, her hair is falling in front of her eyes for the first time. She's started eating raw carrots, counting, and sleeping more often in her own bed. She has great senses. She is energetic, smart, fun-loving, kind, shy, and gentle; I hope these are the traits she holds on to as she grows up.

She wants to watch movies constantly, though we restrict her to one a day. Her favorite movie used to be "Monsters, Inc" (which she called "Bears and Frog"), but now she prefers "Cars" (mostly because of Mater). A couple of days after she first watched it, Rebekah had become Lightning McQueen, I had become Mack (McQueen's transport truck), and Sara Ellen called herself "funny Mater". Her other favorites are "The Incredibles", "Ratoutille", and "Finding Nemo", though she'll occasional want to watch "Beauty and the Beast". Sara Ellen always cheers for the heroes by exclaiming, "No get you!" and fearing for their well-being.

Twenty-seven months ago, I didn't know what I'd do with our child. Now, I don't know what I'd do without her.

Gmail's Buggy IMAP Implementation

As Opera Software's lead QA for Opera Mail, I get a lot of opportunities to analyze the communication between IMAP clients and servers. Gmail is by far the quirkiest and most troublesome IMAP implementation I've seen to date. Gmail's own documentation describes how clients must work around the deficiencies built into their implementation. I understand that Gmail's IMAP implementation is still in beta (a Google norm), but some of the basic design choices are at the heart of the problem, which leads me to believe they won't be changing. These decisions are anti-IMAP (even the IMAP spec. author finds Gmail's IMAP disappointing) and cause Opera users headaches. Here are some of the specific problems:

  • Gmail's labeling system could integrate marvelously with IMAP clients if only it used IMAP keywords. Instead, IMAP mailboxes are used to represent labels. All messages (sent and received) are always available in the "Gmail/[All Mail]" mailbox, so any time a message is labeled, a duplicate message is added to the label's IMAP mailbox. IMAP clients then receive several copies of the same message, none of which integrate with the client-side labeling system. If Gmail had instead used IMAP keywords, only one message would be needed and integration would be seamless.
  • Gmail doesn't allow users to change mailbox subscriptions. Unsubscribing from label mailboxes is a sensible work-around for the above design deficiency, but it's inexplicably not allowed.
  • Gmail doesn't handle standard IMAP flags, such as "\Deleted", "\Answered", and "\Recent". For instance, instead of intelligent handling of "\Deleted" flags in the web interface, users are required to use a variety of work-arounds to mimic the functionality already built into the IMAP protocol.

In addition to the unfortunate design decisions listed above, Gmail's IMAP implementation has a number of bugs:

  • Gmail encodes message headers containing Slavic characters (at least) incorrectly when clients download only message headers. Headers are encoded correctly if a client downloads message bodies and headers together.
  • Gmail sometimes sends malformed BODYSTRUCTURE responses (often used to determine the number and size of attachments to a message before it's downloaded).

To their credit, Gmail has already fixed another bug (in the STATUS command response) we reported to them. I hope they rethink their design decisions and fix the remaining bugs soon, enabling a seamless web interface and IMAP client experience. Otherwise, the burden falls on IMAP clients to implement hackish work-arounds for Gmail, rather than relying on open standards.

Special thanks to Arjan van Leeuwen for investigating many of these issues.

Blog Tag: Meme in One Word Only

A while back, Eirik tagged me. He'd like to know a bit more about me. One...word...at...a...time. So, here goes:

Where is your mobile phone?
shelf

Describe your girlfriend:
girlfriend?!

Your hair:
missing!

Your mother:
young

Your father:
closer

What is your favourite gadget?
40D

What did you dream last night?
forgotten

What do you prefer to drink?
water

Dream car?
Jeep

What room are you currently in?
Dining

Your ex?
n/a

Your biggest fear?
loss

What do you want to be in 10 years?
same

Who did you spend last night with?
family

What are you not?
active

The last thing you did?
waste

What are you wearing?
comfy

Favorite book?
Stardust

The last thing you ate?
pie!

Your life?
good

Your mood?
stable

Your best friends?
faraway

What are you thinking about right now?
life

Your car?
dying

What are you doing right now?
finishing

Your Summer?
sticky

Marital status?
happily

What is on your TV right now?
SG-1

When did you last laugh?
earlier

When did you last cry?
today

School?
done

Helen, Rebekah, Rijk, and David, you're up! Copy the list of questions above and fill in your one-word answers.

Living instead of Waiting

At the end of January, I finally joined the church I've been attending for the past five years (when I was in the United States, anyway). Rebekah and I were married there, Sara Ellen was baptized there, and I play in the handbell choir there. Membership brings a few additional benefits to me: it serves as a gesture of my commitment to the church and it makes me feel more like I'm a part of the church family. I've been reluctant to join not because I didn't want to or because I disliked anything in particular about the church, but because I figured we'd be moving elsewhere soon, so it wouldn't be worth it.

While we still lived in Oslo, a co-worked confided in me that he really wanted a bicycle. He'd wanted a bicycle for a long time, but knew that he might be moving soon and he didn't want to deal with the hassle of moving with a bicycle or trying to sell it before moving. And he'd been telling himself that for the past year, all the while really wanting a bike and missing out on having one. Finally, he bought a bicycle and he couldn't have been happier. His point was that if you put off doing what you want because of something that might happen in the future, you miss out on all the enjoyment you could have had before that future event happens, if ever.

Joining my church didn't take much effort, didn't cost me anything, and didn't have any down side. I just put it off because of something that might happen soon and I was missing out because of it. When I realized that I had no good reason not to join the church now, it was almost as if a burden had been lifted off my chest. It was one less thing to wait for. I learned that if you wait for life to happen, you'll be waiting instead of living. So don't wait: live.

Welcome to The Good Life

For the past couple months, I've been working on upgrading my site to a newer version of Drupal and switching to a new theme. Tonight, I've finally launched the updated site. Some time soon, I'll write more about the upgrade process, but for now I'd just like to welcome everyone to the new site.

As part of the upgrade, I've changed the site name and slogan. It was time to put "Stranger, yet..." to rest. That name, while unique, has been making less and less sense to me. This past week, I've been trying to come up with a unique, fun, and descriptive name for the site and I settled on "The Good Life". Initially, I thought the name might sound a bit like bragging, but my wife has convinced me otherwise.

In any case, I have several new posts in the pipeline and I hope to be updating more frequently now that I'm happy again with the way my site looks and functions. Special thanks to Eirik and Moose for their help with the design. It really wouldn't have turned out nearly so well without them.