A Simplified 2-D Renderer
Approaching the Problem<OpenTag>Presenter required an engine to display two-dimensional objects. Since literature on the subject couldn't be found, it was decided to base the display design on the most common 2-D viewers used today - web browsers.
Microsoft PowerPoint enforces a width:height ratio for presentations, with different zoom levels available for viewing. However, I faced more limitations using the Qt toolkit. While the library supports different font sizes, the width:height ratio of text isn't always the same at different font heights. This means a presentation displayed at one zoom level may not show correct at another zoom level.
Also, PowerPoint assumes the user will be viewing presentations at that set
width:height ratio. I wished to have <OpenTag>Presenter be able to view
presentations at any display dimensions a user wishes. Hence, it was chosen to
emulate the object alignment algorithms of web browsers. Objects would be drawn
relative to each other from left to right. This could easily be represented in
XML with the code ending up almost identical to HTML.
Object AlignmentObjects in a presentation slide are displayed sequentially. By prototyping a renderer design, I decided a simple solution for aligning objects would be to start from (x, y) coordinate (0, 0), passing it to the first object to to display, which would draw the object and then return the (x, y) where the next object can be displayed.
For instance, a slide containing only one image with the margin set at 32
pixels would start rendering at (32, 32), pass those arguments to the image
object which would display the image with it's top left coordinate (32, 32),
then return (x, y) where another object can be drawn. The returned (x, y)
would be (32 + image width + padding, y that was passed as an argument before).
The padding would be needed so text and other objects aren't drawn up to
the right side of the image, causing a cluttered looking presentation.
(32, 32) would be passed to the image and it would return (32 + image width + padding, 32). At the returned coordinate, another object could be drawn by passing these arguments to the next object. This series of coordinates travels across the display aligning objects - which I coined the render cursor. Just as a blinking bar that moves on my monitor as a type, the render cursor moves through the display as objects are displayed as it guides the objects to their coordinates.
Objects are drawn left to right and when a sequence of objects go past the
right margin, there would be a line break, where the last object would
be drawn below the current sequence of objects which form a horizontal line.
A line break would be skipping the height of the highest object on the
current line and then skipping the number of pixels needed for the line
spacing set by the user.
Text HandlingBlocks of text are split up into words. These words are then displayed across the screen and a line break is made once the words reach the right margin. Text can be preformatted (ala the HTML <pre>), but otherwise newlines and tabs are ignored, which eliminates worry about the formatting of XML code. I wanted to accomplish the freedom of HTML.
AnimationObjects in the display can also be animated. However, given the tools, only primitive animation techniques can be used, such as scrolling an image or equation across the screen onto the place where it was decided to be rendered. If an object has its animation property set, it is simply hidden until the user chooses to animate it, at which time the proper algorithm takes over to move the object around the display until it reaches its final destination. Speed and delay properties are available to control the amount of time it takes for the object to reach its destination (which is processor speed dependent).
Limitations of the Implementation
- Object Alignment - The biggest issue with this design is that if the user wishes to create their own objects to display, they are held responsible for properly controlling the render cursor to traverse the 2-D space of the display. It is possible for the coordinates to go over the margins or have objects collide with other objects in the display.
- Low Cohesion - This problem leads to low cohesion where the alignment code must be implemented in every defined object. If a user wishes to extend the functionality of an object another user defined, the alignment code adds another level of complexity to the comprehension of how the former will solve their own problem using existing work. For instance, if a user wished to add a new object type that makes text justified, they would have to read the code I wrote for font handling and figure out how I decided to draw text to the display and how the position of words in blocks of text relate to each other.
- High Coupling - Along the same lines, it leads to high coupling since some defined objects rely on other objects for alignment information. One example is that text relies on information stored in the slide itself to find out what the height of the current line of objects is. So if the height of a line is higher than the text being shown, the text has to be aligned at the same baseline as other objects on the current line. This would mean that objects are aligned to the bottom of the line, just as in word processors and web browsers where if a larger font is used beside a small font, their baselines match. This is similar to lines on loose-leaf where the lowercase "g" would be lower than lowercase "f", but their baselines match.
- Object Baseline - The baseline implementation itself is flawed since the Qt font definition doesn't consistently size objects for different letters of the alphabet, so the y-axis pixel which is the baseline to align to, isn't consistent. The result is that larger fonts appear above smaller fonts in the display on the same line because the larger fonts have more whitespace at the bottom of the Qt font object.
- Environment Dependent - Another problem is that while a user's presentation may look fine in one environment, it may look different and not align correctly in another. This would be a big problem for a professor which creates his/her presentations on a desktop machine and then copies them over to a laptop to use in a lecture. If another operating system, desktop resolution, Qt version, etc. are used, the presentation may show up with overlapping images and text, looking very unprofessional. This may be a price to pay for portability of Qt.
- Scaling - While I designed the renderer to display like a web browser, it is different from a web browser in that scrolling isn't used since the display has exact dimensions. This means that if an image is too wide (say, 14,000 pixels), it has to be scaled down to the display, since a person doesn't want to be scrolling across a slide as spectators wonder what's happening. As with the render cursor, the scaling is a responsibility of the defined objects.
- Out of Bounds - Similarly, objects must detect if they fall off the bottom of the slide, since a sequence of objects are drawn from left to right and top to bottom. If there are a large number of objects or if one object is really tall, other objects would just "fall off the bottom". One solution is to ignore the objects that will "fall off". Another solution to this is that if a slide becomes full, automatically add another slide to the presentation and display the remaining objects on that one. However, the code would be much more complicated than that.