I am nominally on holiday this week. Actually I'm going to be rather busy catching up on work at home and also a few things at the office. However I do reserve the right to ignore anything unpleasant! The highlight of my week will probably be my talk at the Auckland University Computer Science department on Wednesday at noon. Thanks to the CS department for hosting me.
Tuesday, 31 October 2006
Miscellany
Wednesday, 25 October 2006
Partial Ligatures
The screenshot shows some text in DejaVu Sans using my text code and Pango 1.14. "fl" and "fi" are being rendered as ligatures. I'm selecting inside "fl" to show how that works. Basically it's a hack --- a ligature with N characters is divided into N vertical strips of equal width which I pretend are "pseudocharacters", and then I use clipping to draw the individual pseudocharacters. This seems to work OK.
The screenshot also shows another feature of the new text code: our text layout objects (gfxTextRuns) can span DOM node boundaries. In this example the textrun spans the boundary of an <a> element. This enables us to form ligatures across those boundaries but thanks to partial ligature support, we can still style the link element correctly. Not just ligatures but also kerning and shaping benefit from cross-node text layout.
Note: When I said above that any substring should be selectable, that was a lie. Multiple Unicode characters can combine to form "clusters", for example a character with an accent, and selection should always be restricted to cluster boundaries. More consistent support for honouring cluster boundaries is another feature of the new text code. However, I currently don't support clusters spanning DOM node boundaries, because we really have no way to render those, not even a hack.
By the way, I noticed the hairline crack in the fi ligature. It's probably a rounding error that I need to track down.
Tuesday, 24 October 2006
Thinking About Performance
This also highlights an interesting network effect. When a browser has high market share --- especially among Web developers --- developers will optimize for that browser, working around areas where it's slow and taking advantage of features which are fast. Browsers that are trying to break into the market don't get that benefit so they have to try to be faster in all areas where the dominant browser(s) are fast. This is a considerable burden. Hats off to Opera and Safari for doing such a great job.
Of course, even if developers are working around a performance problem in Firefox, we still need to address the problem ... not just to keep up with the competition, but to make life easier for Web developers. And sometimes our performance problems just stop people from using a feature of the Web platform, and we definitely need to avoid that.
Monday, 23 October 2006
Motutapu Island
Motutapu is adjacent to Rangitoto. The two islands are very different --- Rangitoto a brand-new volcano, barren and wild, Motutapo old sedimentary rock, grassy and operated as a farm, lovely in its own way. The Department of Conservation is gradually restoring Motutapu's forest cover, which is excellent although a very long term project.
Mysterious Cargo
At last, I have obtained concrete evidence of New Zealand's clandestine nuclear missile program!
Thursday, 12 October 2006
More Text
Following up on yesterday's issue with line-breaking and kerning... Computing all line break opportunities up front and doing something special when lines could break between non-whitespace characters was going to be too difficult. It's much easier to compute line break opportunities during reflow. Also, I want to have the code structured so that we can have special shaping for glyphs at line ends, and that would apply even when a line breaks at whitespace (or doesn't break at all), which would mean we would want to recompute the text layout at unpredictable times.
So I've opted to provide a hook back to layout from gfxTextRun, allowing it to recover the text used to originally build the textrun (which we can do by recrawling the DOM elements contributing to the textrun). This way textruns can forget the input text and just cache glyphs, and in the uncommon cases where they need the original text again, they can ask for it.
In a few cases (:first-letter and :first-line, I'm looking at you!) it's hard to recompute the text given the information we have stored. For those rare cases I can force the textrun to remember the text at creation time, so I don't have to write complex code to do the reconstruction.
Another round of the delicate dance of tradeoffs completed... for now.
Tuesday, 10 October 2006
Insufficiently Paranoid
You know those people who see the shadowy hand of Microsoft behind every attack on Linux? The people whose rampant paranoia gives those of us with legitimate concerns a bad name? Well, sometimes they're right.
6. Sometime in 2003, I was approached by Richard Emerson (Microsoft's senior vice president for corporate development and stratedy) about investing in SCO, a company about which I knew little or nothing at the time. Mr. Emerson stated that Microsoft wished to promote SCO and its pending lawsuit about IBM and the Linux operating system. But Microsoft did not want to be seen as attacking IBM or Linux. For that reason, Microsoft wanted to further its interest through independent investors like BayStar.
7. I did some research on SCO, and had conversations with Mr. Emerson about it as well. In the course of my research about SCO, I became concerned that SCO might be merely a litigation company. As a result, Mr. Emerson and I discussed a variety of investment structures wherein Microsoft would "backstop," or guarantee in some way, BayStar's investment. In addition, I had discussions with Kenneth Lustig, Microsoft's managing director of intellectual property and Tivanka Ellawala, from Microsoft's corporate development department regarding the SCO deal. As part of these discussions, Microsoft assured me that it would in some way guarantee BayStar's investment in SCO. However, Microsoft would not agree to put anything in writing on this point.
I'm pretty paranoid myself, so it's disturbing to learn that I'm actually not paranoid enough.
Text Progress
Among other things, I've been working away on the new textframe code. I've (re)written the layout part around the new gfxTextRun abstraction and things fit together pretty much as I expected except for a couple of issues.
One issue is that CSS :first-line and :first-letter styling doesn't map well onto the gfxTextRun concept. gfxTextRun assumes that the glyphs used for a chunk of text are largely independent of the formatting of the text into lines. I worked around this by aggressively recreating textruns when :first-line and :first-letter are in use. Ugly but effective and simple.
Another issue that came up was that we really want textruns to span multiple DOM text nodes, if those nodes are visually consecutive and use the same font. This allows chunks of shaped text to be styled differently ( e.g., as a link) without breaking shaping between chunks. Even for Latin text, it allows kerning and ligatures to work across styling boundaries. It also means that a set of text nodes adjacent in the DOM will render identically to a single text node, which is an important property to have. So I had to rework everything to allow a gfxTextRun to span DOM nodes. This added some complexity but I think it's worth it. It will make textrun setup slower, but it will make other things faster because we'll be able to create fewer and bigger textruns, which means fewer expensive calls down into Pango and other APIs.
The next step is for me to implement gfxPangoTextRun. This is requiring me to delve into Pango and figure out how to use its APIs. A key concern is to minimize the memory usage of live textruns. I think I have a scheme that will use four bytes per character in most common cases. We'll see how it goes. Once nice benefit of textrun objects is that those four bytes directly encode glyph indices and advance widths for the text, and we can also keep cairo_scaled_font_t pointers in the textrun, so painting text becomes very simple: very little more than a single pair cairo_set_scaled_font()/cairo_show_glyphs(). Repeated rendering of the same text should be about as fast as it possibly can be from our end ... any remaining problems can be blamed on cairo :-).
One remaining issue I haven't figured out yet is the problem of line endings changing the shape of characters in the textrun. For example, what happens if a font has a "tt" ligature and we hyphenate "cutting"? Also, since you can't kern across line breaks, the advance width of a character could be different if there's a line break after it. Furthermore, OpenType supports glyphs with different shapes when they occur at the beginnning or end of lines (although I don't think Pango does this yet). Currently gfxTextRuns are nearly immutable, which is very nice; the only visible mutable state they can have is cached spacing data. But I think we'll have to solve the line-ending problem by breaking that immutability and adding line ending state. Implementing this with Pango seems tricky though, for example we'll have to somehow un-ligate ligatures. I really don't want to have to recreate the entire layout, or keep enough data around in case we need to do so. For now I think I will just check at textrun creation time whether there are any break opportunities inside "problematic" text (say between two non-space characters) and only keep around the information to recreate the layout if there is at least one such opportunity.
There is a related issue: how do you draw text where the style changes in the middle of a ligature? E.g. a<a href="google.com">f</a>fluent where the font has a ligature for "ffl". I think we'll be doing what everybody else seems to do, a cheesy hack where you use clipping to cut the ffl glyph into three equal horizontal segments. (But you can't use this approach to avoid the un-ligating I mentioned. For example if you applied it to hyphenate "af-fluent", you're likely to have a pixel or two from the top of the first f appearing on the other side of the hyphen, or something equally disgusting.)