Home
Benzene Application Framework Development Journal
 
[Most Recent Entries] [Calendar View] [Friends]

Below are the 4 most recent journal entries recorded in Benzene Application Framework's LiveJournal:

    Friday, November 25th, 2005
    9:18 am
    Cross Platform Text API
    It has troubled me that fonts are such a pain to work with. Why do you have to "install" a font—what makes them so enigmatic that you need to put them in a special centralized directory, and restart your application (or operating system!) just to use it?! Using a font should be as easy as dragging and dropping a graphic into a word processing document. Images are freely shipped along as part of documents to make sure that the recipient sees the document properly, and fonts should be too.

    Not to mention that the interfaces for drawing fonts are TERRIBLE. Most of the time, you can only pick a font name and a size and say "draw this text at coordinates X and Y". If you are lucky, the routine MIGHT tell you how big the enclosing rectangle of the text you drew was—you rarely get to know this in advance. Even more rare is for the system to tell you how wide each character was. Those cases where you get this information often is the result of compromising on using the best text-rendering available.

    The reason the interfaces are so bad is partially due to legitimate complexity of the way fonts are rendered. Sophisticated systems implement kerning and anti-aliasing, which can really make it hard to describe characters in a simple "grid" way. This is why we keep seeing all these miserable Courier fonts everywhere—they're ugly, but at least programmers know every character is the same size. But programmers steer away from even this—now that handling Unicode has made it even more confusing.

    So few people will dare to try and write text handling code if they can avoid it. Especially in cases where text needs to be edited, they try and isolate the content into edit boxes, where system services can handle all of the complexity. This ties the hands of interface designers who might want to implement cool things.

    Two recent discoveries that have pleased me are:

    * Freetype, an open source piece of software for drawing lots of different fonts and extracting the glyph information from them.
    * "Dafont", a nice website which really does a good keyword search of fonts, as well as rendering a piece of text for you in those fonts.

    Operating system vendors have done a lousy job of font handling, and I am going to try and get Freetype to compile in with the Benzene sample apps. This will help avoid the OS-specific code for font handling that I've got right now—fonts have been the key reason why OpenGL has not been satisfactory up until now for my apps.

    UPDATE: 11/27: As of 8:00 am this morning, I'm pleased to say that I have successfully linked FreeType into one of the Benzene sample applications. This is an important step toward making the OpenGL text editing reasonable quality.
    8:50 am
    Apple's Core Data API
    Apple has made a foray into providing what they call a "managed data model" with Core Data. Rather than hand-code classes with instance variables and accessor methods, you design your data structures through entity-relationship modeling. The application framework watches when you change any of this data, and when you do, it knows.

    There are some ramifications of this in terms of undo and redo. From the site:

    "To provide undo and redo functionality in a traditional Cocoa application, you have to programmatically record all of the actions that modify data with calls to an undo manager. Core Data eliminates the need to write this code. Instead, each managed object context maintains an undo manager. This undo manager uses Key-Value Observing (KVO) to keep track of modifications to registered objects. When an undo or redo command is performed by the user, the undo manager can restore the state of the context."

    That's a piece of the battle, although it does not seem the undo/redo information is not saved from one session to the next. There's no work in terms of helping automatically manage the impacts on the display that come when you perform an undo or a redo. You'd have to hook into this "managed object context", and write some kind of callback (Things_To_Do_When_An_Undo_Happens, Things_To_Do_When_A_Redo_Happens). I do not think these things should concern the programmer—when you undo, the framework should automatically put the entire application state to where it was before the command being undone happened. (I'm oversimplifying a bit by saying that, but it's at least somewhat true.)

    Interesting term, though: "managed data model". They use the language of the "observer pattern"—and I'm learning that's a catch phrase that many people understand, and that I should use more often.
    Wednesday, November 24th, 2004
    3:46 am
    Observer Pattern
    I've often mentioned the idea of changing application programming so more responsibility is offloaded to "The System" (or "The Framework") for managing invalidation. What I'm suggesting isn't quite as pathological as "Completely recompute the layout of every page in Microsoft Word on each keystroke". But I do think that programmers could express their code in such a way that looks a lot more like doing the entire computation, and lets the computer figure out how to manage the incremental updates in a "perfect" way.

    Central to achieving this is the ability to monitor the observations that are made of your document as the code is generating pieces of the display. When I mention this, people frequently mention the Observer Pattern. The observer pattern is a good general concept for programmers to think about. Sometimes it's better to not just look at a piece of data and then walking away from it, but rather establish a relationship between the observer and the observed. When a change happens, a notification ("signal" or "callback") is sent to the observer.

    The specifics of what I was imagining was that your document's data structure would be built on an API set up with many different entry points. Each entry point into examining the data structure would correspond to a different kind of observation.

    an example )

    I had a theory about using this approach with a flexible general-purpose data structure (like XML, for example). My idea was that it would be feasible on today's machines to write a full-fledged application (the likes of Microsoft Word or Excel) in such a way that the programmer never had to think about reacting to specific changes in the data, but just let the system take care of it. This can be achieved by breaking the display code into several observers, and re-generating an observer if one one of the pieces of information that it looked at changes.

    For example, in PixelCAD, it is possible to make an icon out of several layers which are composed together...which have rendering effects that are expensive derived computations. Yet each layer is somewhat independent of the others. So it's possible for the display code to observe how many layers there are without delving into the pixel content...and generate a new and independent observer object for each layer. The layers then observe each pixel, so they become dependent on any changes.

    It's straightforward to see how this makes the layers independent, and maybe it seems like it would be easy enough to structure a program in this domain which would react appropriately. But now imagine that one of the special effects for a layer just so happens to visit specific pixels in the layer above or below it. The nice thing is that without adding any special handling code to the program, the invalidation would just work. If the programmer was trying to explicitly manage the display incrementality of layers, it would involve some foresight when adding this new special effect. Otherwise, it wouldn't be possible to get a correct incremental display, due to the assumption that the display of each layer was independent of the underlying data used to produce other layers.

    This is a major piece of the work I was trying to do. When I talk about it, I tend to get into details...like the precise choices of whether HasParent is a separate entry point or not. Or perhaps I'll talk about how the node ID's are hashed together in a clever way to provide very compact storage of the observation list with very few "false positives". I go into those details because these particular choices seem to be what make typical applications built on these premises work surprisingly well on today's machines. The methodology isn't all that terribly novel, it is just something people don't think would generate usable programs--especially not programs that can do fancy tricks like background spell-checking.
    Tuesday, May 18th, 2004
    6:37 am
    LJ-based Error Code Handling
    So given how popular LJ and the Wikis are these days, I'm surprised people aren't building on that for their help systems and having error messages in your program direct you a site. How hard would this be, anyway?

    Let's say you start by identifying errors with GUIDs or something like that in your code:

    ERR errCannotEditReadOnlyFile =
       {
       342348393429823948293843, // special GUID-type number
       "Cannot edit a read-only file.", // an initially cached string
       }


    You put the short string right there in the error. Then make it so the first user who gets that error delivered to them through the UI and clicks on "click here for more info..." makes an LJ or Wikipedia entry get generated. This doesn't seem like rocket science. You just need some sort of server/daemon that would maintain each software package's account and password and do the entry creation, or route the nume
Framework Manifesto and Documentation   About LiveJournal.com

Advertisement