Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » [A5] isn't drawing clipped by a subbitmap?

This thread is locked; no one can reply to it. rss feed Print
[A5] isn't drawing clipped by a subbitmap?
axilmar
Member #1,204
April 2001

Hi all. I have this code:

ALLEGRO_BITMAP *bmp1 = create_sub_bitmap(somebitmap, 100, 50, 250, 200);
ALLEGRO_BITMAP *bmp2 = create_sub_bitmap(bmp1, -20, 40, 50, 40);
al_draw_filled_rectangle(bmp2, 0, 0, 50, 40, al_map_rgb(255, 0, 0));

i.e. I create a subbitmap that is slightly outside of the area of the parent bitmap, and then fill the subbitmap with a color. The drawn rectangle isn't clipped by 'bmp1' though.

Is this normal behavior or am I doing something wrong? do I have to take create of the appropriate clipping myself?

Matthew Leverton
Supreme Loser
January 1999
avatar

Can you show a screenshot of what it looks like?

As far as I know, A5 sub bitmaps are supposed to act just like a clipped translation.

Edit: Oh, you are doing a sub bitmap of a sub bitmap. I'd say it should be clipped to the size of the parent sub bitmap. Not sure if that happens or not.

axilmar
Member #1,204
April 2001

Yeap, I am doing a subbitmap of a subbitmap. Isn't that supposed to be clipped?

Matthew Leverton
Supreme Loser
January 1999
avatar

You should not be able to draw outside of bmp1. You should get a 30x40 rectangle at (0,40) of bmp1, if I am doing the numbers right. (And it should be showing the right half of the white rectangle, not that it makes any difference in this case.)

Note that this behavior is completely different from A4, which (uselessly) silently cropped negative and out-of-bounds coordinates.

axilmar
Member #1,204
April 2001

Here is the actual code:

#SelectExpand
1#include <allegro5/allegro.h> 2#include <allegro5/allegro_primitives.h> 3 4//main. 5int main() 6{ 7 ALLEGRO_DISPLAY *display; 8 ALLEGRO_EVENT_QUEUE *queue; 9 ALLEGRO_EVENT event; 10 ALLEGRO_TIMER *timer; 11 12 //init 13 if (!al_init()) 14 { 15 printf("Allegro could not be initialized.\n"); 16 return -1; 17 } 18 al_install_mouse(); 19 al_install_keyboard(); 20 al_init_primitives_addon(); 21 22 //create resources 23 display = al_create_display(640, 480); 24 queue = al_create_event_queue(); 25 timer = al_create_timer(1.0/60.0); 26 27 //register resources 28 al_register_event_source(queue, al_get_mouse_event_source()); 29 al_register_event_source(queue, al_get_keyboard_event_source()); 30 al_register_event_source(queue, al_get_timer_event_source(timer)); 31 32 ALLEGRO_BITMAP *bmp1 = al_create_sub_bitmap(al_get_target_bitmap(), 100, 50, 250, 200); 33 ALLEGRO_BITMAP *bmp2 = al_create_sub_bitmap(bmp1, -20, 0, 50, 40); 34 ALLEGRO_BITMAP *tbmp; 35 36 //event loop 37 al_start_timer(timer); 38 for(;;) 39 { 40 al_wait_for_event(queue, &event); 41 switch (event.type) 42 { 43 case ALLEGRO_EVENT_KEY_DOWN: 44 if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE) 45 { 46 goto END; 47 } 48 break; 49 50 case ALLEGRO_EVENT_DISPLAY_CLOSE: 51 goto END; 52 53 case ALLEGRO_EVENT_TIMER: 54 tbmp = al_get_target_bitmap(); 55 al_set_target_bitmap(bmp1); 56 al_draw_filled_rectangle(0, 0, 250, 200, al_map_rgb(0, 255, 0)); 57 al_set_target_bitmap(bmp2); 58 al_draw_filled_rectangle(0, 0, 50, 40, al_map_rgb(255, 0, 0)); 59 al_set_target_bitmap(tbmp); 60 al_flip_display(); 61 break; 62 } 63 } 64 65 END: 66 67 //release resources 68 al_destroy_event_queue(queue); 69 70 return 0; 71}

And here is the output:

{"name":"2Jxjs.jpg","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/2\/4\/24af6269ddd64ce07f6d39483036fbab.jpg","w":646,"h":512,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/2\/4\/24af6269ddd64ce07f6d39483036fbab"}2Jxjs.jpg

The drawing in bmp2 is not clipped by bmp1.

Elias
Member #358
May 2000

As Matthew said, sub-bitmaps are not clipped to the parent in A5.

Your code:

ALLEGRO_BITMAP *bmp1 = create_sub_bitmap(somebitmap, 100, 50, 250, 200);
ALLEGRO_BITMAP *bmp2 = create_sub_bitmap(bmp1, -20, 40, 50, 40);

Is supposed to be 100% identical to this:

ALLEGRO_BITMAP *bmp1 = create_sub_bitmap(somebitmap, 100, 50, 250, 200);
ALLEGRO_BITMAP *bmp2 = create_sub_bitmap(somebitmap, 80, 90, 50, 40);

So I think your example behaves as expected - but I didn't look very closely so correct me if it doesn't.

--
"Either help out or stop whining" - Evert

Matthew Leverton
Supreme Loser
January 1999
avatar

Elias said:

As Matthew said, sub-bitmaps are not clipped to the parent in A5.

I realize the implementation "collapses" subs of subs onto the parent, but I'm not saying that detail should affect the behavior as it currently does.

If a function takes an abstract bitmap, it shouldn't have to check to see if it's a sub bitmap. The behavior should be consistent regardless of the source. If that green bitmap were a top-level bitmap, then you'd get clipping.

So I would say it does not behave as expected. I don't see what practical use you get with this behavior. If you want an unclipped sub bitmap of the top-level bitmap, then create it on that.

Edit:

The docs do explicitly say:

Quote:

The parent bitmap's clipping rectangles are ignored.

so of course it's not a bug, but I think that it would be more useful if the clipping were honored. It's been too long since I worked on the sub bitmap stuff to remember how it's implemented, but if it's possible to support both variations, then al_create_clipped_sub_bitmap() would be useful.

I don't mean that it should revert to A4 like clipping. That's even worse. What I think is the most useful is that the origin is still relative like A5's, but nothing is drawn outside the parent bitmap area.

Elias
Member #358
May 2000

Yes, sub-bitmaps are really very simple right now - I wouldn't mind adding more features like that. Recently I'd have needed an al_get_parent_bitmap to get the parent of a sub-bitmap, but all we have is is_sub_bitmap which on its own is a bit useless. I also still want an al_resize_sub_bitmap(x, y, w, h) so you don't have to destroy the old sub-bitmap and create a new one just to shift it by a pixel.

Anyway back on-topic, one solution would be if we in fact update the clipping rectangle of a sub-bitmap when it's created. I think when we first implemented sub-bitmaps clipping was per display so that was not possible - but now it would be very easy to do.

You could then still alter the clipping rectangle to draw outside the parent though. But if we permanently want to clip to the parent we need an extra clipping rectangle for each bitmap - one for the regular clipping we already have and then the additional parent-clipping for the case where a sub-bitmap goes outside of its parent. Which I think is a bit overkill. The other possibility would be to add back chained sub-bitmaps but that adds so much complexity to all drawing code (like, say use a sub-sub-sub-bitmap as texture to al_draw_prim) that I also don't think we want it.

--
"Either help out or stop whining" - Evert

Thomas Fjellstrom
Member #476
June 2000
avatar

It could get a bit complex, you'd have to track subbitmaps original parents, especially if we do add al_resize_sub_bitmap. And either the clipping rects of each sub bitmap has to be recalculated, or the drawing code will have to scan the list all the way down to the base parent.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Matthew Leverton
Supreme Loser
January 1999
avatar

Elias said:

You could then still alter the clipping rectangle to draw outside the parent though. But if we permanently want to clip to the parent we need an extra clipping rectangle for each bitmap - one for the regular clipping we already have and then the additional parent-clipping for the case where a sub-bitmap goes outside of its parent. Which I think is a bit overkill.

This is what I was going to suggest. I don't think it's overkill... All you need to do is have two sets of clipping rectangles. The first is private and unchangeable. The second is public and changeable.

When the user sets the clipping rectangle, the public clipping area becomes the intersection of the private and the one just set. The only code that ever touches that private clipping rectangle is the al_set_clipping_rectangle() function (and of course when creating a sub bitmap).

I think the only side effect to this is that the al_get_clipping_rectangle() could return something different than what the user set. To me, that's not a big deal, but one could also store the user's original request just so it can be returned.

Edit: I think where this breaks down a bit, and is a little less trivial to describe, is when a parent bitmap has user defined clipping. I think the above is still true, but it would require a more sophisticated system to monitor changes to all clipping.

Edit 2: That is, when clipping is changed, you'd have to go down through all sub bitmaps and calculate: public_sub_clipping = public_parent_clipping Intersect private_sub_clipping Intersect user_sub_clipping.

axilmar
Member #1,204
April 2001

Personally, I don't think that drawing on a subbitmap of a subbitmap must be clipped to the parent subbitmap's clipping. It would be indeed an overkill.

But I think that drawing on a subbitmap of a subbitmap must be clipped to the parent subbitmap's visible area, which is permanent during a subbitmap's lifetime.

Thomas Fjellstrom
Member #476
June 2000
avatar

axilmar said:

But I think that drawing on a subbitmap of a subbitmap must be clipped to the parent subbitmap's visible area, which is permanent during a subbitmap's lifetime.

I think you need to rephrase that. It seems like you're saying "No, a subbitmap shouldn't clip against its parent, but yes it should clip against its parent".

I'm assuming you mean it should clip against it's parent, but not it's grandparents.

But what do you mean by permanent? That the rect won't change? What if its parent's position or clipping changes? What about its grandparents?

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

axilmar
Member #1,204
April 2001

I think you need to rephrase that.

A bitmap's visible area is the area left visible by its parent bitmap and all its ancestors. A bitmap's clipping area is the area outside of which drawing is clipped.

Drawing on a subbitmap must be clipped not only by its clipping, which is defined by the user, but by its visible area, i.e. by its area left visible by all the ancestor bitmaps.

An ancestor bitmap's clipping should not affect the clipping of the descentant bitmaps.

Example:

    |------------------------|
    |A                       |
    |      |--------------|  |
    |      |B             |  |
    |      |              |  |
    |  |---|----|         |  |
    |  |C  |////|         |  |
    |  |   |////|         |  |
    |  |---|----|         |  |
    |      |              |  |
    |      |--------------|  |
    |                        |
    |------------------------|

C is a subbitmap of B which is a subbitmap of A.

In the above, the area marked with '///' is the visible area of C, and it is not related to the clipping.

Quote:

But what do you mean by permanent?

I mean that during the lifetime of the bitmap, the visible area of it will not be modified.

Quote:

What if its parent's position

The child bitmap would have to be reconstructed, or moved if a new function proposed above is added to A5.

Quote:

clipping changes?

Nothing. The clipping of a bitmap shouldn't affect the drawing on subbitmaps.

Matthew Leverton
Supreme Loser
January 1999
avatar

axilmar said:

It would be indeed an overkill.

Like I said, it's not hard to do. Implementing for one child is not much more difficult than a long chain.

The core Allegro code doesn't need to be modified. It's good that it stores things in a flattened state optimized for drawing. Each bitmap just needs to know where its children are so that it can update the clipping and offsets when it changes.

Oh, and I disagree with your limitations. I think they are arbitrary and confusing. Either all or no (current method) clipping should be honored, perhaps with different functions.

axilmar
Member #1,204
April 2001

Well, if it is not really an overkill, then I am all for it.

Go to: