[Xr] What happended to the idea of getting rid of the xrs argument?
Bill Spitzak
spitzak at d2.com
Thu Jun 5 11:25:57 PDT 2003
On Thursday 05 June 2003 02:00 am, Michael Meeks wrote:
> On Tue, 2003-06-03 at 05:11, Bill Spitzak wrote:
> > The only way to implement the above in any reasonable way is to have the
> > toolkit provide a wrapper for every Xr call
>
> Perhaps I'm missing something blindingly obvious; but why would a
> wrapper be needed per call ? surely you can manage your own per thread
> closure, with an accessor / push / pop / whatever for your external
> users - if you're concerned about the complexity of exporting the Xr
> API.
What I meant is if there is an XrFoo(xrs,...) call, people have suggested
that this is object-oriented in that you can write a toolkit where you do
widget.Foo(...). As far as I know this can only be done by writing a method
called "Foo" into the toolkit. Then if *new* Xr comes out with
XrWhizBang(...) nobody using the toolkit can call it until the toolkit
authors add widget.WhizBang() to the toolkit.
This is obviously a minor problem, especially for an open-source toolkit. I
am much more concerned with the fact that code that says widget.Foo() will
not port to another toolkit that says widget.XrFoo() or says Foo(widget) or
says XrFoo(widget.XrState()), or any of the hundreds of other possibilities
that I have seen done with Win32 and Xlib GC's. In my opinion, only by having
an implied static XrState can you enforce uniform calling of Xr, and I think
that is vitally important for Xr to be a popular interface.
Maybe instead of enforcing how Xr is called, it can be encouraged, so that
drawing code can be easily cut and pasted between toolkits or between parts
of toolkits. To do this, strongly encourage people to write their code so
that the literal text "xrs" means the current XrState. This can be done with
a macro, a local variable that you use toolkit-specific code to initialize,
or as an argument to functions. So this would be good toolkit-level code:
void MyWidget::draw() {
XrState* xrs = this->get_xrs(); // toolkit-specific
XrRectangle(xrs,...); // not toolkit-specific
XrFill(xrs,...);// not toolkit-specific
NiftyDrawing(xrs);
this->done_with_xrs(xrs); // toolkit-specific
}
An alternative toolkit may be written like this:
void MyWidget::draw(XrState* xrs) {
XrRectangle(xrs,...);
}
Another toolkit might do this (though there are obvious problems with this
solution):
#define xrs (this->something())
Another toolkit might do this (this is what fltk will do):
extern XrState* xrs;
Here is an example of a non-toolkit function. By writing it this way it can
be inserted into any existing program using Xr, or the programmer can cut
pieces out of it and insert them into other parts of their program using Xr:
void NiftyDrawing(XrState* xrs) {
XrFoo(xrs,...);
XrBar(xrs,...);
}
This *may* get the advantages I see from a static XrState. However I still
see problems with this. First of all it requires all inner functions that
draw to somehow get an XrState as an argument. This can be nearly impossible,
for instance fltk has objects called "boxtypes" which draw different borders,
they are currently called with box->draw(x,y,w,h). Contrary to what some
other people seem to think about objects here, the "box" object has NO idea
what "surface" it is drawing on, and I cannot believe this situation is
uncommon (think about fonts, are they expected to have an xrs inside them?).
So the box cannot do anything with itself to find out the xrs. Therefore I
either have to rewrite the method to box->draw(xrs,x,y,w,h) (which would
introduce the fact that XrState exists into the supposedly portable fltk
header files) or I have to use a global variable to hold the current xrs.
I believe this is not fltk-specific, this problem is *extremely* common, and
the end result is that everybody will have to put the xrs into a global
variable sometime anyway.
--
,~,~,~,~ ~ ~ ~ ~
/\_ _|_========___ Bill Spitzak
~~~/\/\\~~~~~~\____________/~~~~~~~~ spitzak at d2.com
More information about the cairo
mailing list