Hello everybody,
I have done some experiments with a backwards compatibility layer for CairoGraphics. The idea was to wrap an arbitrary VisualComponent in a CairoWrapper, and use a CairoGraphicsContext for redirecting the rendering messages to a CairoContext. I have uploaded my code to the public repository. If you want to play with it, have a look at: CairoGraphics-Wrappers CairoGraphics-Wrappers-Examples For the examples, you will need Akamaru 5.1 and CairoGraphics 68.2. The Akamaru.DemoUI will show an additional display mode based on CairoWrapper. CairoWrapper may already work for many VisualComponents which contain only graphics and single-line text labels. Give it a try, and tell me what you find. CairoGraphicsContext supports scaling and transparency. This might be an opportunity to add these features to existing VisualComponents without having to completely rewrite their rendering code for Cairo. However, use it at your own risk - the package is experimental code and not production ready. This is still very experimental, and I am not yet convinced that it is possible to wrap an arbitrary window's component. Many of the widgets coming with VisualWorks bypass the invalidate/damage repair mechanism for updating their contents, and it will be a lot of work to hook into all of the relevant methods (mostly because there's a lot of these methods, they are hard to find, and some of these methods are, well, not very accessible for changes). Another issue is the output of formatted text. It will be hard to convince ComposedText, ComposedTextView, ParagraphEditor and their respective subclasses to use Cairo. It may be possible to replace a ComposedTextView by a Cairo-aware (or Pango-aware) component (similar to Ditto.Label) on-the-fly, but this has still to be done, and it also needs a controller which enables text editing. I'm not sure how much work this would be, but it can probably be done. CairoWrapper does not seem to work with the DoubleBufferingWindowDisplayPolicy so far. If you want to contribute or fix bugs, please use version names like "n.xx.m", where n is the number of the version on which your changes are based, xx are your initials, and m is a sequential number. Please describe your changes in the blessing comment of your version. Have fun with Cairo, Joachim Geidel |
Joachim Geidel wrote: > Hello everybody, > > I have done some experiments with a backwards compatibility layer for > CairoGraphics. [snip] > This is still very experimental, and I am not yet convinced that it is > possible to wrap an arbitrary window's component. Many of the widgets > coming with VisualWorks bypass the invalidate/damage repair mechanism > for updating their contents, and it will be a lot of work to hook into > all of the relevant methods (mostly because there's a lot of these > methods, they are hard to find, and some of these methods are, well, not > very accessible for changes). Yep. I experienced similar barriers while implementing our fast graphics API for MacOS X. The majority of widget code assumes it has direct and immediate control over the display surface (i.e. instant output). This control however, is not available (or at least extremely expensive) on most platforms other than Windows. > Another issue is the output of formatted > text. It will be hard to convince ComposedText, ComposedTextView, > ParagraphEditor and their respective subclasses to use Cairo. It may be > possible to replace a ComposedTextView by a Cairo-aware (or Pango-aware) > component (similar to Ditto.Label) on-the-fly, but this has still to be > done, and it also needs a controller which enables text editing. I'm not > sure how much work this would be, but it can probably be done. > I doubt this would be possible without requiring a full rewrite of large portions of existing code. Text rendering and measurement (i.e. determining character postions) is tightly interwoven with the VM (probably for historical reasons). ParagraphEditor and related classes rely on that. > CairoWrapper does not seem to work with the > DoubleBufferingWindowDisplayPolicy so far. > From what I have learned about the graphics system so far, I would assume this is because Smalltalk makes ad-hoc copies of a GraphicsContext like mad. I had an extremely hard time tracking the countless copies of a GC on MacOS X. This is probably similar with Cairo. A more obvious reason may be that Cairo's drawing is not stored on the buffer medium (Pixmap). BTW: Isn't double buffering redundant with Cairo anyway? > If you want to contribute or fix bugs, please use version names like > "n.xx.m", where n is the number of the version on which your changes are > based, xx are your initials, and m is a sequential number. Please > describe your changes in the blessing comment of your version. > > Have fun with Cairo, > Joachim Geidel > > > Andre |
> Yep. I experienced similar barriers while implementing our fast > graphics API for MacOS X. The majority of widget code assumes it has > direct and immediate control over the display surface (i.e. instant > output). This control however, is not available (or at least extremely > expensive) on most platforms other than Windows. You can't do that in WPF either. So it really only works on DirectFB and Win32. > >> Another issue is the output of formatted >> text. It will be hard to convince ComposedText, ComposedTextView, >> ParagraphEditor and their respective subclasses to use Cairo. It may be >> possible to replace a ComposedTextView by a Cairo-aware (or Pango-aware) >> component (similar to Ditto.Label) on-the-fly, but this has still to be >> done, and it also needs a controller which enables text editing. I'm not >> sure how much work this would be, but it can probably be done. >> > > I doubt this would be possible without requiring a full rewrite of > large portions of existing code. Text rendering and measurement (i.e. > determining character postions) is tightly interwoven with the VM > (probably for historical reasons). ParagraphEditor and related classes > rely on that. > >> CairoWrapper does not seem to work with the >> DoubleBufferingWindowDisplayPolicy so far. >> > > From what I have learned about the graphics system so far, I would > assume this is because Smalltalk makes ad-hoc copies of a > GraphicsContext like mad. I had an extremely hard time tracking the > countless copies of a GC on MacOS X. This is probably similar with > Cairo. A more obvious reason may be that Cairo's drawing is not stored > on the buffer medium (Pixmap). > > BTW: Isn't double buffering redundant with Cairo anyway? around the main drawing to get double-buffering. Michael |
In reply to this post by Andre Schnoor
Andre Schnoor schrieb am 08.09.2007 22:58:
>> Another issue is the output of formatted text. It will be hard to >> convince ComposedText, ComposedTextView, ParagraphEditor and their >> respective subclasses to use Cairo. It may be possible to replace a >> ComposedTextView by a Cairo-aware (or Pango-aware) component >> (similar to Ditto.Label) on-the-fly, but this has still to be done, >> and it also needs a controller which enables text editing. I'm not >> sure how much work this would be, but it can probably be done. > > I doubt this would be possible without requiring a full rewrite of > large portions of existing code. Text rendering and measurement (i.e. > determining character postions) is tightly interwoven with the VM > (probably for historical reasons). ParagraphEditor and related > classes rely on that. their controllers (instances of ParagraphEditor and its subclasses) by new ones implemented from scratch. It's probably cheaper to go that way than trying to hook into the existing classes. By "replacing on-the-fly", I meant something like this (renderOn: is the replacement for displayOn: in CairoGraphics-Wrappers and is used with instances of CairoGraphicsContext only): ComposedTextView>>renderOn: aCairoGraphicsContext "If the receiver is still part of a hierarchy of VisualParts, replace it by a new text view which uses Pango." newComponent := PangoTextView initializedFrom: self. self container ifNotNil: [:c | c component: newComponent. self release.]. "Draw the contents of the text view. All subsequent rendering messages will be sent to newComponent." newComponent renderOn: aCairoGraphicsContext. On the other hand, I am not sure if it's worth the effort in the presence of Widgetry, and people experimenting with making Widgetry use Cairo, IIRC. My initial motivation was to make existing custom graphics components look better by wrapping them in a CairoWrapper. The typical use would be to wrap one VisualComponent, not the complete contents of a window. However, it was tempting to investigate how far one could go... so I have attached a screenshot showing a ComposedTextView rendered with Cairo, including text and scrollbars. Scrolling the text actually works! :-) Even selecting the text is not too far from what it should be. > From what I have learned about the graphics system so far, I would > assume this is because Smalltalk makes ad-hoc copies of a > GraphicsContext like mad. I had an extremely hard time tracking the > countless copies of a GC on MacOS X. This is probably similar with > Cairo. Yes, copying the GraphicsContext was one of the first issues I had to deal with. Setting the clipping rectangle of a copied GC and forwarding this to the CairoContext would totally eclipse all output which was generated later. I have tried to track down the methods where the GraphicsContext is copied in the code of the VisualComponent hierarchy. Instead of copyGC:= aGraphicsContext copy ...draw on copyGC... my code uses aGraphicsContext saveWhile: [:copyGC |...draw on copyGC...]. which will copy the GraphicsContext, but continue to draw on the same CairoContext. The drawing operations are bracketed by calls to cairo_save and cairo_restore. cairo_restore rolls back any temporary changes to graphics attributes like color, line width, scale, clipping etc. I wrote the replacement methods rather mechanically, which means that there are several components where the Cairo compatibility isn't "finished" in any way, because I did not yet deal with the methods which do not copy the GC. > BTW: Isn't double buffering redundant with Cairo anyway? As Michael has already remarked, no. There is an example of Cairo-based double buffering in the examples package. Using a CairoGraphicsContext, you can write this: aGraphicsContext bufferOutputWhile: [:copyGc | self displaySomethingOn: copyGc] where copyGc is a copy of aGraphicsContext. During the execution of the Block, all Cairo output is redirected to a temporary surface using Cairo's cairo_push_group, and copied back to the original surface at the end using cairo_pop_group_to_source and cairo_paint. Of course, if the graphical component which was the reason for using a DoubleBufferingWindowDisplayPolicy is wrapped in a CairoWrapper and uses bufferOutputWhile: in its renderOn: method, double buffering at the displayPolicy level should be unnecessary. Thanks for the feedback! Joachim Workspace.jpg (31K) Download Attachment |
In reply to this post by Andre Schnoor
Andre,
>Yep. I experienced similar barriers while implementing our fast graphics >API for MacOS X. The majority of widget code assumes it has direct and >immediate control over the display surface (i.e. instant output). This >control however, is not available (or at least extremely expensive) on >most platforms other than Windows. FWIW, this is a Wrapper behavior. In Widgetry with FlickerFree, there is no place in the framework that does direct display. And So It Goes Sames ______________________________________________________________________ Samuel S. Shuster [|] VisualWorks Engineering, GUI Project Smalltalk Enables Success -- What Are YOU Using? |
Samuel S. Shuster wrote: Andre,Yep. I experienced similar barriers while implementing our fast graphics API for MacOS X. The majority of widget code assumes it has direct and immediate control over the display surface (i.e. instant output). This control however, is not available (or at least extremely expensive) on most platforms other than Windows.FWIW, this is a Wrapper behavior. In Widgetry with FlickerFree, there is no place in the framework that does direct display. Great. That's is a big achievement. Such a clean behavior will simplify the adoption of Widgetry on our lightning fast graphics API for MacOS X a lot! Does Widgetry also avoid making copies of GCs? Andre |
Andre,
>Does Widgetry also avoid making copies of GCs? Almost all of the time. I think there are about 2 or 3 places it copies, but they may not be needed. And So It Goes Sames ______________________________________________________________________ Samuel S. Shuster [|] VisualWorks Engineering, GUI Project Smalltalk Enables Success -- What Are YOU Using? |
In reply to this post by Samuel S. Shuster <sames@interaccess.com>
On Sep 9, 2007, at 11:00, Samuel S. Shuster wrote:
I think it's important to distinguish (the posters probably all get this distinction, but not sure it's obvious to the casual readers) between two separable issues. One is the technique of doing deferred operations. You can do this a variety of ways. You can do it with a backing store at the OS level. You can use a backing store at the Smalltalk level as the FlickerFree stuff does, which is basically to use a Pixmap via a DoubleBufferingDamagePolicy (and then play by the rules of using only invalidation to update it). You can do as the new single threaded OSX VM does, which is to actually queue real live NSObjects representing the drawing commands until draw time. Or as Andre did with his work which is a combination of VM and VI work, done for the compositional graphics. For completeness sake, Cairographics provides a facility for doing fast buffering too (groupWhile:). The other issue is what the effect of copying GC's is. Copying GC's makes some of the above techniques harder (not all of them), especially when you're trying to layer over them. I think it's wrong to view GC copying as completely bad. If it makes what you're trying to do (i.e. map Cairo cr's on top of them), then it's bad because of that. But writing display code, it seems perfectly reasonable to me to want some way of entering a section of drawing code where you can make changes to the GC that will not affect other sections of code which are rendering to the same eventual back end. I completely love the fact that Cairo cr's have a fast/efficient stack implementation where you can enter a "drawing transaction" where you make adjustments to the current context, that will be forgotten after the "transaction." I've used it prodigiously. Without such a stack model, copying the GC's would be the next best thing. -- Travis Griggs Objologist "Every institution finally perishes by an excess of its own first principle." - Lord Acton |
Free forum by Nabble | Edit this page |