Hi all,
With metan, we discussed Context, blits, drawing and clipping in core.
My proposal would be to remove clipping information from Context and to think about some structure for "Drawing context". This structure could also include other style information and would act as a wrapper around context and used in convenience drawing functions.
The goal is to simplify the base api and modularize the library. I believe that we should allow separate use of any part of the library as much as possible - library supporting all kinds of weird devices can see many uses both with variable subset of the modules.
Arguments to move clipping from Context to drawing are * One use of clipping is convenience when drawing primitives. This should be handled with drawing functions. There, clipping can save some complicated reasoning. * Blits should not respect clipping. Blitting a superset of clip-region is very frequent and even if needed, calculating intersection of two rectangles is very easy. * One use-case of clipping is "user" routines drawing inside windows etc. This can be done using subcontexts (context pointing to part of memory of other context). This has also the advantage of coordinate system being always (0,0) and solves the problem when (clipped) "user" drawing routine would like to use clipping itself. Of course that every context is still "naturally" clipped by (0,0,w,h).
From my own experience, I used clipping very rarely, but I see its
value as a convenience mechanism. Having two variants of drawing functions - one "bare" (unclipped, without implicit style information, etc.) and an optional set of "convenience" functions (clipping, using implicit style info on BGcolor, clipping, aliasing, font, ...) would be the best of both. It still remains a question how to implement such wrapper (structure pointing to a context? context-independent structure? something extensible or fixed? ...). I haven't given it much thought. Any ideas?
If there is an important use-case that I forgot to mention or if there is any technical problem, bring it on.
Best, Tomas
On Sun, May 29, 2011 at 11:29 PM, Tomas Gavenciak gavento@kam.mff.cuni.cz wrote:
Hi all,
With metan, we discussed Context, blits, drawing and clipping in core.
Maybe we could arrange IRC meetings or so; it would be useful for larger infrastructure changes. (I think that Jabber allows for multi-person conversations?)
My proposal would be to remove clipping information from Context and to think about some structure for "Drawing context". This structure could also include other style information and would act as a wrapper around context and used in convenience drawing functions.
If I understand correctly, we would then have a structure that describes a bitmap and its organization, and another structure that contains drawing settings? Let's say, a Canvas/Surface/Bitmap and a Context?
The goal is to simplify the base api and modularize the library. I believe that we should allow separate use of any part of the library as much as possible - library supporting all kinds of weird devices can see many uses both with variable subset of the modules.
Well, modularization is a nice things, but please, do not overengineer that. Myriads of independent sub-libraries tend to create a dependency mess, complicate building of dependent projects, and slow things down.
Arguments to move clipping from Context to drawing are
- One use of clipping is convenience when drawing primitives. This
should be handled with drawing functions. There, clipping can save some complicated reasoning.
- Blits should not respect clipping. Blitting a superset of
clip-region is very frequent and even if needed, calculating intersection of two rectangles is very easy.
Not sure about this; for myself I would say that a graphics system that does not respect clipping with some primitives and does with some others is confusing (how to remember which is which? Does a textured triangle, which is both a blit and a primitive, respect clipping?)
- One use-case of clipping is "user" routines drawing inside windows
etc. This can be done using subcontexts (context pointing to part of memory of other context). This has also the advantage of coordinate system being always (0,0) and solves the problem when (clipped) "user" drawing routine would like to use clipping itself. Of course that every context is still "naturally" clipped by (0,0,w,h).
Now that's what I call a brilliant idea! :-)
From my own experience, I used clipping very rarely, but I see its value as a convenience mechanism. Having two variants of drawing functions - one "bare" (unclipped, without implicit style information, etc.) and an optional set of "convenience" functions (clipping, using implicit style info on BGcolor, clipping, aliasing, font, ...) would be the best of both.
I'm not sure; in accordance with Murphy's Law, the user will find out that she needs a function that uses one of the advanced features but not the rest (e.g. antialiasing but not clipping).
I would rather vote for Guido van Rossum's way of "there should be preferably one correct way to do it". :-)
It still remains a question how to implement such wrapper (structure pointing to a context? context-independent structure? something extensible or fixed? ...). I haven't given it much thought. Any ideas?
Depends on what settings the structure should contain. If it should contain any kind of color information (color, filling, background, anything) then it will always need a pointer to the real bitmap data to convert the color into appropriate format. We can, of course, do it in every function call, but that costs us some time (negligible for larger elements, horrible for PutPixel - however, PutPixel and probably HLine are special anyway - they probably need an explicit color parameter anyway because there is a chance that color will be changed wildly often, and writing it into the context every time would also waste time).
So, if the new Context structure contains any information that is somehow bound to the underlying bitmap, then it should be (IMO) bound to that bitmap, and rebinding should require a special function call (because it needs recalculations that cost time).
OTOH, it would be useful to have a Context store a color in the most precise way so that it does not become subject to accumulation of rounding errors; it makes sense to store what the user *meant* (which is not necessarily what she gets).
Best regards,
Jiri Dluhos
Hi!
With metan, we discussed Context, blits, drawing and clipping in core.
Maybe we could arrange IRC meetings or so; it would be useful for larger infrastructure changes. (I think that Jabber allows for multi-person conversations?)
It was more like an informal talk about meaning of life and clipping rectangle, but if you are not afraid, you are probably welcome. I preffer a mail conversations, because it's less time consuming and we don't need to get to the computer at the same time.
My proposal would be to remove clipping information from Context and to think about some structure for "Drawing context". This structure could also include other style information and would act as a wrapper around context and used in convenience drawing functions.
If I understand correctly, we would then have a structure that describes a bitmap and its organization, and another structure that contains drawing settings? Let's say, a Canvas/Surface/Bitmap and a Context?
Yes, somethink like that. It may store clipping rectangle/fb,bg color/font style/line thickness...
The goal is to simplify the base api and modularize the library. I believe that we should allow separate use of any part of the library as much as possible - library supporting all kinds of weird devices can see many uses both with variable subset of the modules.
Well, modularization is a nice things, but please, do not overengineer that. Myriads of independent sub-libraries tend to create a dependency mess, complicate building of dependent projects, and slow things down.
Well, doing everything as one big library is even whorse than that.
I would personally settle here for two or three layers of libraries here.
- One use-case of clipping is "user" routines drawing inside windows
etc. This can be done using subcontexts (context pointing to part of memory of other context). This has also the advantage of coordinate system being always (0,0) and solves the problem when (clipped) "user" drawing routine would like to use clipping itself. Of course that every context is still "naturally" clipped by (0,0,w,h).
Now that's what I call a brilliant idea! :-)
Trully indeed. I would like to have this implemented.
From my own experience, I used clipping very rarely, but I see its value as a convenience mechanism. Having two variants of drawing functions - one "bare" (unclipped, without implicit style information, etc.) and an optional set of "convenience" functions (clipping, using implicit style info on BGcolor, clipping, aliasing, font, ...) would be the best of both.
I'm not sure; in accordance with Murphy's Law, the user will find out that she needs a function that uses one of the advanced features but not the rest (e.g. antialiasing but not clipping).
I would rather vote for Guido van Rossum's way of "there should be preferably one correct way to do it". :-)
That one often makes one wrong way to do it.
It still remains a question how to implement such wrapper (structure pointing to a context? context-independent structure? something extensible or fixed? ...). I haven't given it much thought. Any ideas?
Depends on what settings the structure should contain. If it should contain any kind of color information (color, filling, background, anything) then it will always need a pointer to the real bitmap data to convert the color into appropriate format. We can, of course, do it in every function call, but that costs us some time (negligible for larger elements, horrible for PutPixel - however, PutPixel and probably HLine are special anyway - they probably need an explicit color parameter anyway because there is a chance that color will be changed wildly often, and writing it into the context every time would also waste time).
I see no problem in this. If you have a pointer to structure with colors they could be stored in pixel format from the start.
So, if the new Context structure contains any information that is somehow bound to the underlying bitmap, then it should be (IMO) bound to that bitmap, and rebinding should require a special function call (because it needs recalculations that cost time).
OTOH, it would be useful to have a Context store a color in the most precise way so that it does not become subject to accumulation of rounding errors; it makes sense to store what the user *meant* (which is not necessarily what she gets).
Not sure about this. I'ts C library and I'm not "Quiche Eater". (and this is one more reason to have two layer library, one layer for "Real Programmers" consisting of API which is optimalized for shooting yourself in the leg (and building a graphics library dedicated for your purpose) and one ready to use for "Quiche Eaters".
Hi,
Maybe we could arrange IRC meetings or so; it would be useful for larger infrastructure changes. (I think that Jabber allows for multi-person conversations?)
It is good to get a quick check on an idea, but I must say I prefer email threads. One has time to think about it and it is very time-flexible.
My proposal would be to remove clipping information from Context and to think about some structure for "Drawing context". This structure could also include other style information and would act as a wrapper around context and used in convenience drawing functions.
If I understand correctly, we would then have a structure that describes a bitmap and its organization, and another structure that contains drawing settings? Let's say, a Canvas/Surface/Bitmap and a Context?
Something like that. I think about it as a DrawingContext that is bound to a Context (e.g. points to a context, but not the other way around, you could even have several DC for one Context).
The goal is to simplify the base api and modularize the library. I believe that we should allow separate use of any part of the library as much as possible - library supporting all kinds of weird devices can see many uses both with variable subset of the modules.
Well, modularization is a nice things, but please, do not overengineer that. Myriads of independent sub-libraries tend to create a dependency mess, complicate building of dependent projects, and slow things down.
Thanks for pointing that out. I am trying hard to be aware of that. For me, separation speeds development up rapidly, as I can actually make (API-preserving) changes without fiddling with unrelated but heavily entangled code.
My perspective is that we are creating a very powerful library (in terms of supported kinky 2bit HW etc.) and that many users would prefer only some of the API (having their own text-rendering, event management, etc.).
(I often find myself struggling with a library I wanted to use for one simple thing X, trying to make it do only X and not Y and Z as well, frustrated with the results)
I recently encountered "the golden rule of API design": If in doubt, leave it out. (rationale: if your API is neat, clean and stable, anyone can build a library providing the advanced feature they always wanted).
Arguments to move clipping from Context to drawing are
- One use of clipping is convenience when drawing primitives. This
should be handled with drawing functions. There, clipping can save some complicated reasoning.
- Blits should not respect clipping. Blitting a superset of
clip-region is very frequent and even if needed, calculating intersection of two rectangles is very easy.
Not sure about this; for myself I would say that a graphics system that does not respect clipping with some primitives and does with some others is confusing (how to remember which is which? Does a textured triangle, which is both a blit and a primitive, respect clipping?)
In other libraries, i see two things (or uses, though not entirely separated): 1) Sometimes you want the basics - load a bitmap, blit it, put some pixels, draw a line, perhaps do simple text. You want it simple and fast. I would personally still prefer to have this kind of interface, as in GP_Line(context, x1, y1, x2, y2, color); No state involved. 2) If you do something polished, you want all kinds of transparency, aliasing, clipping and nice font options. For that I hate the libraries that offer you some of those combinations under awkward names and letter combinations. Here having a state with such settings (aliasing, kind of transparency, font settings) is a great help and even allows the user to choose quality (aliasing on/off) simply, without carrying global settings around manually.
- One use-case of clipping is "user" routines drawing inside windows
etc. This can be done using subcontexts (context pointing to part of memory of other context). This has also the advantage of coordinate system being always (0,0) and solves the problem when (clipped) "user" drawing routine would like to use clipping itself. Of course that every context is still "naturally" clipped by (0,0,w,h).
Now that's what I call a brilliant idea! :-)
Unfortunately, there are some rough edges with nonadressability of <8bpp pixels, but I still want to implement it. Maybe we can use some walkaround (I have to think about it more).
From my own experience, I used clipping very rarely, but I see its value as a convenience mechanism. Having two variants of drawing functions - one "bare" (unclipped, without implicit style information, etc.) and an optional set of "convenience" functions (clipping, using implicit style info on BGcolor, clipping, aliasing, font, ...) would be the best of both.
I'm not sure; in accordance with Murphy's Law, the user will find out that she needs a function that uses one of the advanced features but not the rest (e.g. antialiasing but not clipping).
I belive we should aim for all combinations, if possible. But not exactly my area ...
I would rather vote for Guido van Rossum's way of "there should be preferably one correct way to do it". :-)
Hmm, and what would that be? Guido chose that so that Python is widely-readable. I do not see us having such requirement.
It still remains a question how to implement such wrapper (structure pointing to a context? context-independent structure? something extensible or fixed? ...). I haven't given it much thought. Any ideas?
Depends on what settings the structure should contain. If it should contain any kind of color information (color, filling, background, anything) then it will always need a pointer to the real bitmap data to convert the color into appropriate format. We can, of course, do it in every function call, but that costs us some time (negligible for larger elements, horrible for PutPixel - however, PutPixel and probably HLine are special anyway - they probably need an explicit color parameter anyway because there is a chance that color will be changed wildly often, and writing it into the context every time would also waste time).
Right. Putpixel is definitely part of core. I would like to avoid excessive repeated modifications to some kind of context to change color etc.
So, if the new Context structure contains any information that is somehow bound to the underlying bitmap, then it should be (IMO) bound to that bitmap, and rebinding should require a special function call (because it needs recalculations that cost time).
I thought about the DC as being bound to one Context (so noneed to pass both to functions), but using one DC for several contexts seems like good alternative. DC can then contain the PixelType, so it does not *have* to point to a Context. Still, where do you see the use-case for using one DC for Contexts of different PixelTypes?
OTOH, it would be useful to have a Context store a color in the most precise way so that it does not become subject to accumulation of rounding errors; it makes sense to store what the user *meant* (which is not necessarily what she gets).
"Most precise way" might be more trouble than use and giving the user what she meant is awfully hard. It is easier to make it easy for (and to teach) her to *get* what she wants. Even without mentioning palettes and such. Her program will mostly likely use one PixelType and she won't care which (+ conversions from constants and loaded images to the PixelType). If she uses several PixelTypes willingly, I believe she would prefer to have control over what is happening to her colors.
Tomas
-------------------- Let's give them enough rope.
Hi,
Arguments to move clipping from Context to drawing are
- One use of clipping is convenience when drawing primitives. This
should be handled with drawing functions. There, clipping can save some complicated reasoning.
- Blits should not respect clipping. Blitting a superset of
clip-region is very frequent and even if needed, calculating intersection of two rectangles is very easy.
Not sure about this; for myself I would say that a graphics system that does not respect clipping with some primitives and does with some others is confusing (how to remember which is which? Does a textured triangle, which is both a blit and a primitive, respect clipping?)
Hmm, what about this: We are most probably going to have a family of "styled" drawing functions (where style may include dithering, font, bgcolor, transparency, quality), be it through some drawing context or otherwise. Let the "styled" functions respect clipping and the "crude" ones not. ("crude" probably means only blit, putpixel, rect).
Good coding, Tomas
Not sure about this; for myself I would say that a graphics system that does not respect clipping with some primitives and does with some others is confusing (how to remember which is which? Does a textured triangle, which is both a blit and a primitive, respect clipping?)
Hmm, what about this: We are most probably going to have a family of "styled" drawing functions (where style may include dithering, font, bgcolor, transparency, quality), be it through some drawing context or otherwise. Let the "styled" functions respect clipping and the "crude" ones not. ("crude" probably means only blit, putpixel, rect).
Sounds logical, but my experience speaks differently (sorry). There are two technical arguments against this:
1. Doing clipping at lower levels is pretty easy while clipping higher-level primitives is much more challenging (clipping horizontal lines that form a rectangle is trivial; clipping the whole rectangle means ritual dances with vectors and the result might not be a triangle anymore).
2. Low-level primitives require clipping anyway (drawing over screen borders must be safe - unless you want the user to compute all clipping at higher levels, which is a pretty sadistic approach). Allowing the user to specify the rectangle manually brings no additional cost.
Best regards,
Jiri Dluhos
Hi!
Sounds logical, but my experience speaks differently (sorry). There are two technical arguments against this:
- Doing clipping at lower levels is pretty easy while clipping
higher-level primitives is much more challenging (clipping horizontal lines that form a rectangle is trivial; clipping the whole rectangle means ritual dances with vectors and the result might not be a triangle anymore).
- Low-level primitives require clipping anyway (drawing over screen
borders must be safe - unless you want the user to compute all clipping at higher levels, which is a pretty sadistic approach). Allowing the user to specify the rectangle manually brings no additional cost.
I was thinking about removing clipping in favor of subcontexes. All drawing then would be explicitly clipped to fit into subcontext which must be done anyway and we would get reasonable and consistent interface.