nanogui: Drawing transparent bitmaps


Previous by date: 4 Mar 2007 19:54:49 +0000 Re: show the jpeg, Greg Haerr
Next by date: 4 Mar 2007 19:54:49 +0000 problem GrGetFontList, Thomas Postler
Previous in thread: 4 Mar 2007 19:54:49 +0000 Re: Drawing transparent bitmaps, Greg Haerr
Next in thread:

Subject: Re: [nanogui] Drawing transparent bitmaps
From: Roberto ####@####.####
Date: 4 Mar 2007 19:54:49 +0000
Message-Id: <45EB23B3.7020706@tnw2000.org>

Hi Greg,
sorry about so much text, but its a little bit complicated
to explain my thoughts.

>
> Greg Haerr wrote:
>
>> : I had a similar idea like you. My gain was to  have
>> : a transparent color in order to be able to draw an
>> : invisible window with a transparent gif inside.
>> : Intention was to show only the visible part of the gif.
>>
>> Roberto - I have several comments on your post, and
>> am concerned about the proper way to implement
>> what you've done.  See comments below!
>>
>>
>> : I began in the fb driver like you but found out that the
>> : the clipping of the windows wont work with this mechanism
>> : since several windows may overlap each other.
>>
>> Clipping should long have been handled above the driver
>> layer, so I'm concerned as to why we're worried about
>> clipping when we're talking about transparency.  Is this
>> because you want to implement non-rectangular windows
>> and want alpha-blending outside the normal window
>> frame?
>>  
>>

Yes, my intention is to have a non-rectangular window (what do you mean 
with "outside the normal window frame"?) , but with fb drivers <32BPP.

My Idea is to have a window with an invisible background. This means
that the window is existing, it is causing an event if someone clicks 
into it,
but it is not visible. If a gif (a gif with transparency parts, i.e. a 
circle) is drawn to this window, the only thing you can see is the 
visible part of this picture. Attachment1 should illustrate
my desire. I know that there is already a way to do things like this, 
the tux example is a non-rectangular window. But the transparent parts 
of tux.gif
are hard coded, you have to recompile the tux code when changing the gif.
Generating the tuxmask at runtime in the application would mean that
the gif is opened and read twice, one time by nanox, one time by the 
application to generate
the mask.

Now imagine that the application wants to draw an additional line across 
the window
using GrLine. In this case, the mask array has to be changed again. I 
had the impression,
that this technique is firstly complicated for the applications 
programmer, since he has
to calculate the mask array each time his self, secondly, the work is 
done twice, one time
in the application to generate the line mask, one time by nanox to draw 
the line.
Looking forward to the performance, I  think  it is better  to do this  
one time
in the server/engine.

Now to your question about the clipping. I try to explain my thought, 
please
refer to attachment1. In attachment1 is a window named window3.
window3 is rectangular and has transparent parts. window 3 is above 
window2 and below
window4. If something changes in window3 (i.e. the gif should move some 
pixels to the left),
it has to be redrawn. Now I had several thoughts about this:

Following scenario :
The screen driver (i.e. fb16) gets a 32bit value with alpha channel. 
With an alpha channel=255
the screen driver draws the pixel, with an alpha channel=0, this pixel 
is not drawn.

One way for redrawing :

Destroy window3 and draw it again.  Without any modifications in the 
server/engine
and without any mask as used in the tux example, this will cause a 
redraw of
    - the parts of window0 (=background picture) which are not covered 
by window2 and 4
    - the visible parts of window2 which are covered by window3
      -> the invisible parts of  window2 which are covered by visible 
parts of  window3
           are are left.
    - no redraw of  window 4 at all -> parts of window3 are left.
When drawing window3 again, the part of window3 which is covered by window4
is not drawn since it is clipped out.
Besides, clearing out window2 completely and redrawing it would cause 
flickering.

I don't know any more why I discarded to use the same technique as used
in the tux demo inside the server/engine, but there were some reasons. I 
always had problems
that something wasn't redrawn correctly, at the wrong time or not at all.

So I began to modify the code in the nanox and engine directory and 
tried following things:

Way 2:
Clear out every window with a transparent background and draw everything 
again
beginning at window0.
-> This works basically, but flickering is a real problem. This is no 
solution.

Way 3:
Don't clear out anything. Just redraw every window, beginning at 
window0, but
only the part which is covered by window3. I modified GsSetClipWindow to
ignore windows with a transparent background. I also used pixmaps which 
were
set as background using GrSetBackgroundPixmap. The advantage here is 
that using
the pixmaps as background will cause a blitting of the already 
(offscreen) painted
pixmap to the screen.
-> works better, but still flickers.

Way 4:
Like way3, but I modified GsSetClipWindow in a way that it does examine
the alpha channel (of all overlapping windows with transparent background)
and modifies the clipping region. I think this is what you  mean with

Clipping should long have been handled above the driver
layer

I tried it and basically this worked without flickering.
But too slow. Generating the clipping regions and evaluating the the 
regions
in GdBlit was too slow.

Way5:
Like way4, but I didn't used the clipping regions, but allocated a field of
chars, each char representing the visibility of one pixel -> clipmap 
(255= visible, 0=invisible).
The clipmap is only valid for the overlapping regions. Only for speed I 
decided to evaluate
the clipmap in the driver.

Finally I reviewed everything:
1.) every window (pixmaps, too) got an alpha map (as replacement for the 
missing alpha channel when using lower resolutions). The alpha map is 
filled by the higher level
drawing functions.
2.) the alpha maps are evaluated by GsSetClipWindow in srvclip2.c only 
where needed
(overlapping parts of windows with transparent background). Result is 
something I called
"clipmap".
3.) The clipmap is evaluated in the driver. An invisible pixel means: 
don't draw it.
4.) When redrawing a window with a transparent background, the area 
below must be redrawn,
too.

Up to now this is working with a good performance and without flickering 
within an application
window. The TNW++ example3 should demonstrate this. Moving transparent 
windows is currently
only working within an application window using GrMove, but with 
flickering.  You can check
this out in example3 by clicking to the "Place in Runtime" label, then 
clicking to a widget and then use the arrow keys to move it.

I also added a tux2 example which does not use an array for shaping. 
This works fine since
GrMove is used here. With the window managers container windows I still 
have some problems.
But I think the solution is not far away.

>> : So I tried to introduce an "alpha map" which is added to each
>> : nanox window. If any drawing routine draws to the window,
>> : the alpha map is filled with the information which pixel
>> : is visible and which not.
>>
>> This should already be able to be handled using
>> 32bpp drawing with ARGB, such that the upper
>> byte is the alpha channel, without adding any new
>> maps. We would have to implement the ability to
>> convert 32bpp ARGB to lower resolutions for
>> systems with, say 16bpp, which isn't handled now,
>> since nano-X always demands drawing in the native
>> hardware format, except for the MWIMAGEHDR
>> structure.
>>
>>  
>

Yes, thats true, but if using i.e. GrLine, the information about
visible and invisible pixels is lost for future redraw operations of
other overlapping windows, since GrLine (respectively GdLine)
directly calls the drivers drawing routines. If a window has a 
transparent line across,
the windows below must be redrawn in this area.

>> In the next step I modified the clipping functions
>> : to be able to calculate the visible/invisible pixels if several
>> : windows are overlapping. Greg already mentioned that the
>> : engine doesn't support any additional values to the driver, so
>> : I store this information in a global pointer which can be accessed
>> : by the fb drivers.  I know this is a little bit dirty,
>> : but I had no idea how to solve this in a different way
>>
>> This sounds like something to do with creating overlapped
>> windows with an alpha channel, including the ability
>> of the system to handle alpha blending outside of the
>> interior (user) area?
>>  
>

No, the only reason for the global pointer was to handle it over to
the fb drivers in a simple way.

>
>>
>> : Anyway, with this modifications I was able to have several transparent
>> gifs
>> : without any rectangular background overlapping each other.
>> : The application simply has to use the GR_ARGB macro to
>> : define the color, where A=0 means transparent and A=255 
>> non-transparent.
>>
>> Was this for the window borders?
>>
>>  
>

What I tried to say is that i.e. GrLine(...)  with a prior call of
GrSetGCForeground(...,GR_ARGB(0,x,x,x) will draw a transparent line.

>
>> :
>> : You may download what I described above (based on version 0.91)
>> : at ftp.tnw2000.org. But I concentrated in the Nano-X api.
>> : May be it does not work completely with the win32 api.
>> : Contact me if you have problems.
>>
>> I'll check it out 
>

I would be very happy about your feedback.

>> Regards,
>>
>> Greg
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: ####@####.####
>> For additional commands, e-mail: ####@####.####
>>
>>
>>  
>>
>
>
> ------------------------------------------------------------------------
>
>



Previous by date: 4 Mar 2007 19:54:49 +0000 Re: show the jpeg, Greg Haerr
Next by date: 4 Mar 2007 19:54:49 +0000 problem GrGetFontList, Thomas Postler
Previous in thread: 4 Mar 2007 19:54:49 +0000 Re: Drawing transparent bitmaps, Greg Haerr
Next in thread:


Powered by ezmlm-browse 0.20.