Posted in Bookmarks on July 31, 2016 05:23 AM
Posted in Bookmarks on July 31, 2016 05:23 AM
Posted in Bookmarks on February 05, 2016 11:50 PM
Posted in Bookmarks on February 04, 2016 01:16 AM
Posted in Bookmarks on February 04, 2016 12:24 AM
Posted in Bookmarks on January 20, 2016 07:56 PM
Posted in Bookmarks on October 29, 2015 12:15 AM
Iain Banks, in 1988 (!), correctly predicting the problems of suspense writing in the age of smart phones:
Stories set in the Culture in which Things Went Wrong tended to start with humans losing or forgetting or deliberately leaving behind their terminal. It was a conventional opening, the equivalent of straying off the path in the wild woods in one age, or a car breaking down at night on a lonely road in another. A terminal, in the shape of a ring, button, bracelet or pen or whatever, was your link with everybody and everything else in the Culture. With a terminal, you were never more than a question or a shout away from almost anything you wanted to know, or almost any help you could possibly need.
—The Player of Games
Posted in Bookmarks on August 06, 2015 10:59 PM
When E.’s new friend from school comes over to our house, the two of them like to spend half their time playing, and the other half sitting and reading books. Which is awesome.
Posted in Weblog on November 05, 2014 05:55 PM
I’m returning at last to my series on building a simple HTML rendering engine:
In this article, I will add very basic painting code. This code takes the tree of boxes from the layout module and turns them into an array of pixels. This process is also known as “rasterization.”
Browsers usually implement rasterization with the help of graphics APIs and libraries like Skia, Cairo, Direct2D, and so on. These APIs provide functions for painting polygons, lines, curves, gradients, and text. For now, I’m going to write my own rasterizer that can only paint one thing: rectangles.
Eventually I want to implement text rendering. At that point, I may throw away this toy painting code and switch to a “real” 2D graphics library. But for now, rectangles are sufficient to turn the output of my block layout algorithm into pictures.
Since my last post, I’ve made some small changes to the code from previous articles. These includes some minor refactoring, and some updates to keep the code compatible with the latest Rust nightly builds. None of these changes are vital to understanding the code, but if you’re curious, check the commit history.
Before painting, we will walk through the layout tree and build a display list. This is a list of graphics operations like “draw a circle” or “draw a string of text.” Or in our case, just “draw a rectangle.”
Why put commands into a display list, rather than execute them immediately? The display list is useful for a several reasons. You can search it for items that will be completely covered up by later operations, and remove them to eliminate wasted painting. You can modify and re-use the display list in cases where you know only certain items have changed. And you can use the same display list to generate different types of output: for example, pixels for displaying on a screen, or vector graphics for sending to a printer.
Robinson’s display list is a vector of DisplayCommands. For now there is only one type of DisplayCommand, a solid-color rectangle:
To build the display list, we walk through the layout tree and generate a series of commands for each box. First we draw the box’s background, then we draw its borders and content on top of the background.
By default, HTML elements are stacked in the order they appear: If two elements overlap, the later one is drawn on top of the earlier one. This is reflected in our display list, which will draw the elements in the same order they appear in the DOM tree. If this code supported the z-index property, then individual elements would be able to override this stacking order, and we’d need to sort the display list accordingly.
The background is easy. It’s just a solid rectangle. If no background color is specified, then the background is transparent and we don’t need to generate a display command.
The borders are similar, but instead of a single rectangle we draw four—one for each edge of the box.
Next the rendering function will draw each of the box’s children, until the entire layout tree has been translated into display commands.
Now that we’ve built the display list, we need to turn it into pixels by executing each DisplayCommand. We’ll store the pixels in a Canvas:
To paint a rectangle on the canvas, we just loop through its rows and columns, using a helper method to make sure we don’t go outside the bounds of our canvas.
Note that this code only works with opaque colors. If we added transparency
(by reading the
opacity property, or adding support for
in the CSS parser) then it would need to blend each new pixel with
whatever it’s drawn on top of.
Now we can put everything together in the
paint function, which builds a
display list and then rasterizes it to a canvas:
At last, we’ve reached the end of our rendering pipeline. In under 1000 lines of code, robinson can now parse this HTML file:
…and this CSS file:
…to produce this:
If you’re playing along at home, here are some things you might want to try:
Write an alternate painting function that takes a display list and produces vector output (for example, an SVG file) instead of a raster image.
Add support for opacity and alpha blending.
Write a function to optimize the display list by culling items that are completely outside of the canvas bounds.
If you’re familiar with OpenGL, write a hardware-accelerated painting function that uses GL shaders to draw the rectangles.
Now that we’ve got basic functionality for each stage in our rendering pipeline, it’s time to go back and fill in some of the missing features—in particular, inline layout and text rendering. Future articles may also add additional stages, like networking and scripting.
I’m going to give a short “Let’s build a browser engine!” talk at this month’s Bay Area Rust Meetup. The meetup is at 7pm tomorrow (Thursday, November 6) at Mozilla’s San Francisco office, and it will also feature talks on Servo by my fellow Servo developers. Video of the talks will be streamed live on Air Mozilla, and recordings will be published there later.
Posted in Weblog on October 22, 2014 10:00 PM
In systems that rely heavily on “most popular” lists, like Reddit or Hacker News, the rich get richer while the poor stay poor. Since most people only look at the top of the charts, anything that’s not already listed has a much harder time being seen. You need visibility to get ratings, and you need ratings to get visibility.
Aggregators try to address this problem by promoting new items as well as popular ones. But this is hard to do effectively. For example, the “new” page at Hacker News gets only a fraction of the front page’s traffic. Most users want to see the best content, not wade through an unfiltered stream of links. Thus, very little input is available to decide which links get promoted to the front page.
As an experiment, I wrote a userscript that uses the Hacker News API to search for new or low-ranked links and randomly insert just one or two of them into the front page. It’s also available as a bookmarklet for those who can’t or don’t want to install the user script.
Randomize HN (drag to bookmark bar, or right-click to bookmark)
This gives readers a chance to see and vote on links that they otherwise wouldn’t, without altering their habits or wading through a ton of unfiltered content. Each user will see just one or two links per visit, but thanks to randomness a much larger number of links will be seen by the overall user population. My belief, though I can’t prove it, is that widespread use of this feature would improve the quality of the selection process.
The script isn’t perfect (search for FIXME in the source code for some known issues), but it works well enough to try out the idea. Unfortunately, the HN API doesn’t give access to all the data I’d like, and sometimes the script won’t find any suitable links to insert. (You can look at your browser’s console to see which which items were randomly inserted.) Ideally, this feature would be built in to Hacker News—and any other service that recommends “popular” items.