A5 clipping
Neil Walker

How do you turn off clipping for a bitmap?

I tried al_set_clipping_rectangle(0,0,0,0);

thinking it might do something similar to the old set_clip function but it simply results in nothing being drawn to.

Thomas Fjellstrom

I don't think you can turn off clipping. Just reset it to 0,0,w,h.

Peter Wang

I have been considering to add the convenience function:

void al_reset_clipping_rectangle(void);

Matthew Leverton

Unrelated to the question at hand, but on the topic of convenience methods:

al_push_state(int state);
al_pop_state();

I use those a lot.

Neil Walker

^ it's not really a convenience when it's additional to what you're used to with A4 :P

I guess if there's not much to gain in not having a clipping region then I'll just chop out the code.

Carrying on the theme of unrelated but similar observations, I noticed from the early A5 to the current branch, the 'image addon' functions have got less and less (now only 3 functions). Why not just bring them into the core given almost everybody wants to load images as it seems odd that you have to call the image initialisation from an add-on to use a core bitmap load method.

Matthew Leverton

No answer will satisfy both sides of that argument. You can search the [AD] mailing list archive if you want to know the reasoning.

In the end, it comes down to consistency (i.e., either all loaders in core or all in an addon) and slippery slope issues with other addons.

Mark Oates

I have been considering to add the convenience function:

void al_reset_clipping_rectangle(void);

I think an ALLEGRO_CLIP_REGION might be better, with

  • ALLEGRO_CLIP_REGION al_compose_clipping_region(int x, y, w, h);

  • void al_set_clipping_region(ALLEGRO_CLIP_REGION region);

  • ALLEGRO_CLIP_REGION al_get_clipping_region();

I've already come across a few instances where multiple layers of clip regions are necessary. Specifically, a window widget with a clip region contains child widgets, like a text block that has its own region. After the text block is drawn, it will need to revert to the previous state before drawing the rest of the children.

The store/restore states are too much for this particular function, and the existing

int x, y, w, h;
al_get_clipping_rectangle(&x, &y, &w, &h);
//
al_set_clipping_rectangle(&x, &y, &w, &h);

seems like it could be cleaned up a little.

Also, my proposed method fits in with the way other allegro components function, eg:

ALLEGRO_BITMAP *previous = al_get_target_bitamp();
al_set_target_bitmap(new_target);
// draw stuff;
al_set_target_bitmap(previous);

Matthew Leverton

Sub bitmaps are better for nesting translations + clipping.

Edit:

If you run ex_clip for speed comparisons, you should take note that it also is timing creating and deleting a sub bitmap, which is an unrealistic disadvantage.

For something like GUI widgets that rarely change, I don't think it makes sense to use clipping and translations to position the child widgets. A sub bitmap (created once and saved for future use) will be faster than setting clipping all over the place.

Mark Oates

Hmm... the biggest problem I have with sub-bitmaps is that they don't do sub-pixel antialiasing when drawing primitives. And since all my widgets are drawn with primitives it doesn't look so hot.

Also, as it is now, child widgets are not drawn with coordinates relative to their parents. When a parent is moved, it repositions the children with them. There are a few benefits to this, including no need to translate or pass relative coordinates between child-parent widgets for mouse events, and it maintains a consistency across all widgets for mouse axes events.

Matthew Leverton

the biggest problem I have with sub-bitmaps is that they don't do sub-pixel antialiasing when drawing primitives

Why don't they?

I don't rely on sampling. It seems to be pretty slow for very little gain in terms of drawing widgets. I simply draw something a bit bigger first with some opacity to it. When you're dealing with smoothing a single pixel line on a high res monitor, it seems fine to me.

Quote:

child widgets are not drawn with coordinates relative to their parents

What is that supposed to mean?

If I have a 640x480 desktop at (0,0) [relative to the Allegro display] containing a window at (16,16) [relative to the GUI desktop], and if I want to add a button to the window on its top,left corner of its inner panel, I have to call move_widget(btn, 16, 16)?

Thomas Fjellstrom

What is that supposed to mean?

I take it to mean all widgets are like A4 widgets, they all have their own global coordinates.

Matthew Leverton

I take it to mean all widgets are like A4 widgets, they all have their own global coordinates.

Right now I store everything relative, but I have a "get absolute coords" function. If it turns out to be some sort of bottleneck, it would be trivial to store x and abs_x (etc) for each widget. Both systems have uses.

But how you store it internally doesn't really matter with regard to sub bitmaps vs clipping. That's really what I'm asking about: how does using sub bitmaps make that any more difficult?

Obviously with sub bitmaps, if the "root" bitmap moves, then you have to recreate your sub bitmaps. But moving widgets is not such a common occurrence that it's problematic. (And if it were, you could give each moving (draggable) framed window its own bitmap.) The code would be hardly any different from repositioning global coordinates.

Thomas Fjellstrom

I just assume that everything is drawing to absolute coords rather than relative.

Right now I store everything relative, but I have a "get absolute coords" function. If it turns out to be some sort of bottleneck, it would be trivial to store x and abs_x (etc) for each widget. Both systems have uses.

My Canvas lib uses relative positions, but I've been thinking about caching the absolute positions like I've been caching the transform and other bits.

Mark Oates

Why don't they?

I'm not sure. It has something to do with a stencil buffer or an FBO or something fancy, I dunno.

Quote:

I don't rely on sampling.

Not me. I like my lines smooooth. 8-)

how does using sub bitmaps make that any more difficult?

More overhead. Creating an extra bitmap, managing it, x, abs_x, abs_x+w, etc for each child, or mouse axes functions need to pass through a parent widget, or you need to keep it all in check by feeding translations. [edit]If you're using a sub-bitmap, it seems logical that you would be keeping everything relative to the 0,0 of the bitmap and then drawing the sub-bitmap to a different location, thus requiring a non-absolute child coordinate strategy[/edit].

Otherwise all you have to do is

void parent_mouse_axes_move_func(void *obj, ALLEGRO_MOUSE_EVENT *ev)
{
    UIParentFrame *f = static_cast<UIParentFrame *>(obj);
    f->x += ev->dx;
    f->y += ev->dy;
    for (int i=0; i<(int)f->child.size(); i++)
    {
       f->child[i]->x += ev->dx;
       f->child[i]->y += ev->dy;
    }
}

done. 8-)

I have to call move_widget(btn, 16, 16)?

I usually compose every parent/child group at (0,0) and then move it.

Matthew Leverton

I'm not sure. It has something to do with a stencil buffer or an FBO or something, I dunno.

A sub bitmap of the backbuffer should work no differently than clipping. Have you tried?

Quote:

More overhead.

One could easily use an absolute coordinate system with a sub bitmap approach.

#SelectExpand
1void parent_mouse_axes_move_func(void *obj, ALLEGRO_MOUSE_EVENT *ev) 2{ 3 UIParentFrame *f = static_cast<UIParentFrame *>(obj); 4 f->x += ev->dx; 5 f->y += ev->dy; 6 for (int i=0; i<(int)f->child.size(); i++) 7 { 8 f->child[i]->move_rel(ev->dx, ev->dy) 9 } 10} 11 12void widget::move_rel(x, y) 13{ 14 this->x += x; 15 this->y += y; 16 al_destroy_bitmap(this->canvas); 17 this->canvas = al_create_sub_bitmap(root, this->x, this->y, this->w, this->h); 18}

And actually, it wouldn't be too hard to add repositioning sub bitmaps into Allegro core, I don't think. Then if you made the sub bitmaps relative to the parent, you would never have to create/destroy sub bitmaps. (Only move the single bitmap on the container that moved.)

So anyway, the point is, I don't think absolute vs relative has anything to do with sub bitmaps vs clipping.

And ultimately, they (sub bitmap vs clipping) are probably fairly equivalent in terms of code.

Mark Oates

A sub bitmap of the backbuffer should work no differently than clipping. Have you tried?

I tried back then and something went wrong with drawing from the backbuffer to another bitmap, I'm not sure why. That's where I stopped and haven't worked on it since. There was also the problem of needing to keep the backbuffer as a freely available drawing surface. I would have had to get all the renders before drawing the scene, possibly clearing it and needing to redraw the whole thing. I dunno, there was a lot I didn't explore. I'll look into it some more.

Quote:

void widget::move_rel(x, y)

I was going to say you have the extra hit of creating/destroying a bitmap, but I guess with sub-bitmaps it's not such a big deal.

Quote:

And ultimately, they (sub bitmap vs clipping) are probably fairly equivalent in terms of code.

Apart from the code I posted before, there is little extra needed to accommodate it in how my system is coming together.

As it is now, the parent widget contains the children, and the ui_manager only knows of the parent. So each child is dependent on the events fed through the parent. Though this isn't necessary, it keeps things "in the family" :D;)

I may change it later, parent/child is still in experimental phase.

Thread #606493. Printed from Allegro.cc