How to XOR text on top of a gauge in a miniwindow

Posted by Nick Gammon on Mon 11 Aug 2008 09:53 PM — 2 posts, 8,816 views.

Australia Forum Administrator #0

This shows how to XOR text on top of a gauge in a miniwindow. First - what is the problem? Say I have a gauge that can change colour (using a gradient), and I want to overlay text on top of it. The text might be the text equivalent of what the gauge is showing (eg. 50% mana). The trouble is, on top of a gradient, no one colour of text works well. Let's choose black:

No, that is hard to read. How about white?

What we really want is for the text to continually change colour, so it is readable. This is how to do it. First - the end result:

Here is the code to do that:


    
    
    win = GetPluginID ()
    wint = win .. "/text"
    
    gauge_width = 100
    gauge_height = 20
    
    gauge_x = 20
    gauge_y = 100
    
    percentage = 80
    
    -- Make visible window to show gauge
    
    WindowCreate (win, 0, 0, 200, 200, 12, 0, 0xFFFFFF)  -- create window
    WindowShow (win,  true)  -- show it 
    
    -- Make window for text, add font to it
    
    WindowCreate (wint, 0, 0, gauge_width, gauge_height, 12, 0, 0x000000)
    WindowFont (wint, "f", "Dina", 9, false, false, false, false) -- define font (Dina)
    
    font_ascent = WindowFontInfo (wint, "f", 2)
    
    -- what to say
    
    message = "Important info"
    
    -- shadow
    
    WindowRectOp (win, 1, gauge_x + 1, gauge_y + 1, gauge_x + gauge_width + 1, gauge_y + gauge_height + 1, 0x999999, 0)
    
    -- draw gradient
    
    WindowGradient (win, gauge_x, gauge_y, gauge_x + gauge_width * percentage / 100, gauge_y + gauge_height, 
                    ColourNameToRGB ("darkred"), 
                    ColourNameToRGB ("green"), 
                    1)  -- left to right
    
    -- frame it
    
    WindowRectOp (win, 1, gauge_x, gauge_y, gauge_x + gauge_width, gauge_y + gauge_height, 0x000000, 0)
    
    -- write text in second window
    
    WindowText (wint, "f", message, 0, 0, 0, 0, 0xFFFFFF, false) -- draw message
    
    -- turn into image
    
    WindowImageFromWindow(win, "text", wint)
    
    -- blend text onto gauge (half-way down)
    
    WindowBlendImage (win, "text", 
                      gauge_x + 1,    -- left
                      gauge_y + gauge_height / 2 - font_ascent / 2,   -- top
                      gauge_x + gauge_width,   --right
                      gauge_y + gauge_height,   -- bottom
                      33,  -- blend mode - XOR
                      1)    -- opacity - 100%
    

What this does is draw the text into a second window (called "wint" above). This second window is never shown directly, it is only used to hold an image which is them blended with an XOR (blending mode 33) on top of the gauge. The XOR operation inverts the underlying bits. I have made the text white on black, as black does not change the underlying image with an XOR. However white will invert it - thus each part of the text inverts the gauge under it.

Amended on Wed 13 Aug 2008 06:09 AM by Nick Gammon
Australia Forum Administrator #1

Another approach is to make a shadow, which looks like this:

Here is the code to do that:


    
    
    win = GetPluginID ()
    
    gauge_width = 100
    gauge_height = 20
    
    gauge_x = 20
    gauge_y = 100
    
    percentage = 80
    
    -- Make visible window to show gauge
    
    WindowCreate (win, 0, 0, 200, 200, 12, 0, 0xFFFFFF)  -- create window
    WindowShow (win,  true)  -- show it 
    
    WindowFont (win, "f", "Dina", 9, false, false, false, false) -- define font (Dina)
    
    font_ascent = WindowFontInfo (win, "f", 2)
    
    -- what to say
    
    message = "Important info"
    
    -- shadow
    
    WindowRectOp (win, 1, gauge_x + 1, gauge_y + 1, gauge_x + gauge_width + 1, gauge_y + gauge_height + 1, 0x999999, 0)
    
    -- draw gradient
    
    WindowGradient (win, gauge_x, gauge_y, gauge_x + gauge_width * percentage / 100, gauge_y + gauge_height, 
                    ColourNameToRGB ("darkred"), 
                    ColourNameToRGB ("green"), 
                    1)  -- left to right
    
    -- frame it
    
    WindowRectOp (win, 1, gauge_x, gauge_y, gauge_x + gauge_width, gauge_y + gauge_height, 0x000000, 0)
    
    -- write text in window - shadow (black) - offset by 1 pixel right and down
    
    WindowText (win, "f", message, gauge_x + 1,    -- left
                      gauge_y + gauge_height / 2 - font_ascent / 2 + 1,   -- top
                      0, 0,
                      ColourNameToRGB ("black"), false) -- draw message
    
    -- write text in window - white
    
    WindowText (win, "f", message, gauge_x,    -- left
                      gauge_y + gauge_height / 2 - font_ascent / 2,   -- top
                      0, 0,
                      ColourNameToRGB ("white"), false) -- draw message
    
    

What this does is draw the text first in black, 1 pixel to the right and 1 pixel down, which is the shadow. It then draws on top of that in white.