Recent blog entries for nicholasl

I'm going to forget about text handling entirely.

I've figured out what my problem with postscript output was. It seems that my bounding box was ranging from (0,0) to (+x,-y) which placed the image below the printed page. This is because Fresco places the origin in the top-left corner. A fix to the code is on-going.

But I won't be able to check it in until we have our CVS repository back. Stefan Seefeld, our fearless leader, is mangling the CVS tree as we migrate from one server to another, with a new build system and a new directory structure. Good luck, Stefan!

I'm hacking my local tree in preparation of my Grad Project presentation. The first two things I did were to remove the 33fps cap and force full redraws every frame. This actually ups the frame-rate for GL and lowers it for libArt, which is what I want. Of course, I'll have to produce a switch for it so that I can turn it off when I want to show the damage-cleaning system Berlin has.

Alpha-blended 3d objects are busted at the moment. If a cube is supposed to be rendered in alpha, we want to be able to see through the front and to the back. If we use either back-face culling or depth testing, we will lose parts of the cube that should've been visible. Hence, we must render back-to-front in this case, which means that I'm buzy writing a painter's algorithm sort. It's buggy and I don't know what's wrong.

GLX only allows one thread to hold the Context at a time. This is usually fine for any game because they aren't threaded, or if they are they do all their video operations from the same thread. Not so with Berlin. If we receive a request to the DrawingKit from across CORBA, the ORB will launch a new thread to deal with the request. Hence, the GLDrawingKit needs to have a worker-thread built in. This thread must be provided by the Console, since the Console will also want to make GL calls (to handle the mouse pointer, specifically).

Last rant, I talked a bit about how the full DrawingKit API is exposed to the client. I more recently noticed that there's a parallel problem with the Traversals. The server doesn't have a copy of the scene graph ever, instead it just holds a reference to the top level node and asks it for an iterator, then walks through all the children. Because a Graphic can be implemented by the client, so can an GraphicIterator and a malicious iterator can produce a cyclic scene graph, an infinite depth problem, an infinite breadth problem. There's a few more problems in the general case; a client can pass an exception over CORBA to the unsuspecting server thereby killing it. Or it can never return, knowing that the server is blocked waiting for a response. This is all very bad. I'd like to move the whole scene graph representation inside of the server so that it can enforce sanity within the scene graph. All children of a Graphic must be registered with the server, no more client-provided Iterators, thank you. This means, however, that if a client wants to traverse the scene graph, it must do so by asking the server for a reference to it, which probably isn't such a bad idea from a security perspective anyways.

Wow, I'd almost completely forgotten about this page; I found it when cleaning up my bookmarks list.

Berlin has progressed a lot since my last entry. But it's regressed rather badly too. The good news is the SDL+GL are in, thanks to the tremendous efforts of Tobias Hunger. I wrote up a new DrawingKit that renders to PostScript and got commit privileges to the tree. Ben Bucksch started up a new project called fresco-contrib and I've put a few clients in there including a client-side Graphic. At school, I've got a linux box with Berlin installed, but the 3d hardware requires XFree 4.2.0 and so I'll either have to wait for Brendan Robinson to package it, or install it myself. I plan to hold out for as long as I can.

The bad news is that some optimizations that got checked in early January have busted a lot. Bounding boxes are messed, clicked buttons fail to trigger, layout fails to bring sizes back down, and probably more. Things got very ugly, very quickly.

I've got a few things on my mind. One of them is the problem with positional event handling delivering coordinates in screen-pixels. Clearly this is useless to a widget, so we should deliver them in widget-space. Except that when we do so, things like dragging a scrollbar thumb will get confused because the widget receiving the coordinates is the thumb, not the scrollbar, so the coordinates never change as the thumb moves. D'oh. The solution is to make the scrollbar receive the event, not the thumb. But the only way for the scrollbar to check whether or not the thumb got hit is to use a Traversal—which would make the thumb receive the event. UNLESS, the scrollbar (dragpane) creates its own custom traversal class. Yuck!

Secondly, it occured to me when writing the client-side Graphic demo that the client is allowed to call any function on the DrawingKit. Now, things like draw_path and foreground I can understand, but things like transformation, clipping and save/restore? The server is supposed to be able to handle anything that a client might do. Well, a client that calls restore a few times might just crash the server. Similarly, being able to change the clipping and trafo to draw all over the screen might be a security problem too. At first I thought that maybe I could get away with giving the DrawTraversal access to the full DrawingKit and casting it into a reduced one before passing it off the the Graphic. Unfortunately, the Graphic could then narrow it to the larger interface and two, a client can implement its own Traversal anyhow. That's right a client can just ask for any DrawingKit at any time, out of the blue.

While I'm thinking about restructuring the interface between the Traversal and the DrawingKit, I'd like the DrawingKit to know more about what's going on in the Traversal. Currently, the DrawingKit can't create display lists because it gets created for one traversal and destroyed at the end. I'd like to have a PersistantDrawingKit class that sticks around and gets informed by the traversal before it goes to render each node of the scene graph. I haven't thought it all through yet either, but if the Traversal knows what's damaged and can ask the DrawingKit to do a fast-track rendering instead of traversing the nodes, we could avoid a lot of overhead, and most importantly network traffic.

Lastly, Berlin needs a TextKit. There's two parts to this issue: the TextKit and the DrawingKit. The TextKit needs to ask the DrawingKit for metrics on fonts that it is capable of drawing. This poses the WYSIWYG times multiple DKs problem. When you write something up in GL, then go to print it, the metrics on the font may change and so the line breaks may move and what you end up with won't be WYSIWYG at all. I want to impose one proviso: all DKs that report a font of the same name must have the same Metric. In other words, if there's a TTF file cmr.ttf, call it "Freetype AMS Computer Modern Roman" and the TeX metafont "Metafont AMS Computer Modern Roman." That should suffice, though in sufficiently bizarre environments it could still break. Mind you, when that happens I'd rather fix the underlying issue of conflicting fonts than change our architecture. The TextKit is responsible for performing the text layout. Given the font and a paragraph (string), it creates a graph where the glyphs (accented characters) and subgraphs are the verticies while the edges contain kerning/advance and soft-hypenation data. Ligatures and bidi are handled as separate graphs, where the entire subgraph can be treated as a glyph in the master graph.

    Notes on ligature processing: ligatures must be able to separate between the characters for the purpose of picking one character and not the other. Further, it should be capable of handling words like "shelfful" correctly, that is, without producing any ligatures.

    Notes on kerning: beware the sliding dot problem. In a string such as "T.W.Lewis," the dots should slide directly next to the characters. The mistake is in forgetting to keep the space after the dot and before the next letter. Similarly, don't slide the dot at the end of a sentence either. The graph should be exposed to a client that wants to provide professional editing capabilities.

(Given that a paragraph contains attributes such as alignment.) All the TextKit needs now, is the space into which it may perform its layout. This space is defined by having a baseline (or many baselines) that intersect two borders. Imagine a piece of three-hole, blue lined paper with a vertical pink line at the left margin and a yellow line along the right.

Oh no, I'm not thinking very well. I was going to talk about complex sheets of paper (multiple pink and yellow lines masking off where the next may and may not go) and then suggest that overflow be broken into pages. The plan was to make a simple multiline view be one baseline and allow the overflow to layout the remainder on similar pages then render each page stacked vertically. Unfortunately, I completely forgot about handling in-line graphics that are supposed to float around the text, such as an image that is associated with a word, but is to be right-aligned. And how should it be aligned, center of image to baseline of text? Or the bottom? (W3C's CSS suggests the bottom, come to think of it.) The other thing I want to address is fitting text along paths that aren't straight, like making a circle. Do you simply rotate the glyphs and place them in the right spot, or should the glyph itself be distorted entirely? I should ask a typographer.

More to come if I figure anything out, I suppose.

There's a lot of work for me to do. I've had to deal with my major corporate clients having colliding hard deadlines, school projects galore and my Project Advisor wants me to stop coding 100% and start writing English. I'd understand if he wanted me to start documenting stuff, but he doesn't. He seems to want me to do something in the project management side of things, as in the people part, not the computer part. Naturally, I only half-understand what he means. :-)

Stefan semi-liked my half-baked Console restructuring patch. I accidentally added a dependency from GGIConsole to MESAGGI which I didn't intend and I've fixed that. Stefan's idea is to allow the Console and the DK to use any API that they want when communicating with one another, where the DK has the smarts to handle different Consoles, which is great. It means creating a consistent ConsoleBase interface for libBerlin to use.

I still don't know what belongs in there. For example, my patch removes all dependency on Drawables from libBerlin. But things like width, height and resolution were offered on a per-drawable basis. The purpose of multiple drawables remains a mystery to me, though Stefan says that it exists to allow for multi-buffering. But if that's the case, shouldn't the width and height still be global? Now suppose they are and the Console hides the existence of a Drawable from libBerlin -- if the Console even has a Drawable at all.

What we've done is imply that on any display Berlin will run has a finite height and width. Which is true so far, but is it a safe assumption forever? What about other properties like resolution or pixelformats? Does a display-postscript display have a resolution?

We had to pull drawables out of the public Console API in order to implement hardware accelerated GL. Will we have to pull something else in order to support another display? I wish I knew.

Another fellow just popped his head up with a patch that fixes Unifont in the GLDK. The Unifont Project is a bitmap font that implements the entire Unicode character map. Berlin uses it as a fallback when no other fonts can be found. (Or in the case of GLDK, freetype support just plain isn't implemented yet.) This is great because it means that I don't have to fix it myself. I was planning to do that as soon as possible after landing the SDL/GL rewrite by rewriting the GLUnifont code using display lists and texfonts. It's a lot of work saved.

As for the SDL/GL rewrite, it's finally coming along. I've decided to move the Pointer out of the DrawingKit and into the Console. Also, the GLDrawingKit will never use any Drawable. Instead, it'll ask the Console to activate its the GL context mode, so that the GLDK can make whatever GL calls it wants. This is by far the cleanest solution, except that it means that the server would be running without any Drawable at all and the server tries talking to the Drawable in several places. Interestingly, most of them have to do with the mouse pointer and that's now in the Console too. The other calls to Drawables have been diked in my latest patch too. I'm no longer releasing hwaccel revisions because my latest patch doesn't actually support hwaccel yet. In fact, it even breaks SDL completely, but at least everything will work perfectly when I'm done.

I now understand why I couldn't create a SDLDrawableGL. The console tries to keep them in a STL vector of type DrawableTie<SDLDrawable>. I'm still looking for a good source of documentation on the Standard Template Library, but I now know what a vector is: an array of similarly typed objects, type-enforced at compile time. I should consider doing the same thing with my new Pointer/PointerTie setup because every time you call Console::pointer() you get a new object instead of a reference to the pointer you want. How should we handle multiple pointers? Or should we?

So my Grad Project Advisor is no longer Dr. Rice (prof of mathematics) but Mr. Combeer (director of information technology). Neither of them are much for programming, but at least the IT director can hire technology people (read: programmers) who might understand Berlin. I just have to make sure he asks the interviewees the right questions.

I'm getting positive feedback from the Berlin crew. Or at least from the ones who have 3d cards. They're giving me the warm fuzzies! There's a lot of chatter on berlin-design, finally. I thought of using save unders (or backing store, not sure which these days) to implement the mouse pointer and allow the same API for clients. X does this for transient windows like popups, if I'm not mistaken. Another idea came out, to avoid the work-associated-with-the-scene-graph for windows that are obscured. Unfortunately, there's nobody in Berlin who can convert 2d pixel coordinates into a scene graph node, short of doing all the associated-work. The proposal is to add such intelligence into the drawing kit, the only place allowed to talk in terms of pixels.

Complicated. I'd rather get some basic hardware acceleration into Berlin now and think about such things later.

I originally thought that I would need to split the SDLConsole into two modes, dependant on the DrawingKit, but as it turns out, the SDLConsole object is fine, my changes only apply to the SDLDrawable object. What I really, really want is an SDLGLDrawable object. Whether it should live in the GL DK or the SDL Console is a matter I'd rather leave up to the policy makers, but I'll do something if no one tells me what to do. I already made one attempt to update the code w.r.t. choosing multiple Drawables, but failed miserably. Perhaps a knowledge of C++ would help, as there seem to be some tricks involved in guaranteeing (at compile time) than an object is of the right type, and my SDLDrawableGL != SDLDrawable. Oh well.

Or maybe not like that. In the interest of getting the GL support landed, I'm going to go the minimal-impact route. I still want to have a Drawable implemented in GL calls (meaning that draw_line uses glVertex instead of Brezenham and put_pixel). But today, I've got schoolwork. It's not like last week with two math tests, but more like next week with two math assignments.

I'm keeping this diary so I can show my Grad Project advisor that the work I'll be presenting is my own. They're concerned about me presenting 'something' without being able to seperate my own work from anyone elses. Hopefully this diary will help.

I'm working on the Berlin project ATM. I've already released a patch that makes it run in OpenGL on top of SDL. Of course, with the patch applied, GGIMesa mode no longer works. I'm taking this as an opporunity to redesign the way that the Berlin Console and DrawingKits are defined.

The deal is that we've got lots of bits and pieces and no good organization. I'm sifting the code into categories to allow a better matching of optimized implentations. See, the LibArtDrawingKit implements the DrawingKit interface on top of basic Drawable operations. There's a slow impl of Drawable operations on top of a generic Framedevice, but if the fd is actually a GGIFramedevice, then we can use the GGIDrawable that runs faster. Like that.

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!