Menu

#212 Support for 24-bit bitmaps in TButtonGadget

8
pending
GUI (33)
1
2022-12-29
2022-07-18
No

The rendering of buttons on our toolbars is pretty dated. In particular, the greying of disabled buttons is using a technique that works best on 4-bit graphics and that may produce ugly and inadequate results for bitmaps with more colours. And overall, the rendering algorithms assume colour-indexed bitmaps with a palette (8-bit or less colour depth) and does not work at all for direct-colour bitmaps without palettes (typically 24-bit "true colour"). We should improve this!

See also:

Related

Bugs: #120
Bugs: #37
Discussion: 6e4ad3ad
Discussion: Transparent bitmaps with TButtonGadget
Discussion: 89cd9b96
Discussion: Tip for nicer gadget buttons
Discussion: TControlBar
Feature Requests: #213
News: 2022/07/owlmaker-build-6160-update
Wiki: OWLNext_Roadmap_and_Prereleases

Discussion

  • Vidar Hasfjord

    Vidar Hasfjord - 2022-07-19
    • status: open --> pending
     
  • Vidar Hasfjord

    Vidar Hasfjord - 2022-07-19

    Support for 24-bit bitmaps has been added on the trunk [r6122], and the revision has been merged into Owlet [r6123].

    One of the big problems with the old code was that it did colour mapping — replacing certain colours in the source bitmap by system colours. See TButtonGadget::GetGlyphDib. It calls TDib::MapUIColors, which transforms the given glyph. GetGlyphDib is called behind the scenes by TButtonGadget::BuildCelArray, which in turn is called in TButtonGadget::SysColorChange and TButtonGadget::GetDesiredSize. The latter function is called as part of gadget window initialisation and sizing. So the colour mapping just happened as a side-effect of this — all very obscure!

    With regard to rendering proper transparency, the effect of the colour mapping was to replace TColor::LtGray by TColor::Sys3dFace in the given glyph. However, pixels of this colour are not rendered. Instead, a mask is created based on the transformed bitmap with TColor::Sys3dFace as the transparent colour. The mask is then used to finally render the glyph (using GDI function MaskBlt). Using a mask allows the theme-based background to show through transparent areas of the glyph bitmap, as the background is rendered first (see TButtonGadget::PaintBorder). The rendering of the face itself is delegated by TButtonGadget::PaintFace to TUIFace and happens in TUIFace::PaintBm.

    Apart from being obscure, the colour mapping using TDib::MapUIColors does not work for 24-bit bitmaps, since this function works on the DIB's palette, and 24-bit bitmaps do not have a palette.

    My revision removes the colour mapping altogether. Mapping certain colours in the glyphs to system colours no longer make sense in modern Windows, I would think, but let me know if you see a compatibility problem. Without the mapping, the code is now much clearer about using TColor::LtGray as the transparent colour. However, perhaps we should change this also, and instead use the upper left pixel. The latter is a common convention, I think. For example, it is supported by Windows' own Image Lists (see ImageList_LoadImage).

    The other big problem with the rendering was, as mentioned in the ticket description, that it had very poor rendering of disabled buttons. I have hence replaced this part of the code altogether with a new fading routine. It dries and fades the colours in the glyph towards TColor::Sys3dFace. See the revised TUIFace::PaintBm, which now calls the new helper function MakeFadedCopy_.

    The new solution should be compatible with bitmaps of all colour depths. I've tested 4-bit, 8-bit and 24-bit, and it seems to all work as intended. But please review and test!

     

    Related

    Commit: [r6122]
    Commit: [r6123]

Anonymous
Anonymous

Add attachments
Cancel