Difference between revisions of "LMD VCL - Glyph Transparency"

From LMD
Jump to: navigation, search
(Standard TImageLists)
 
(One intermediate revision by the same user not shown)
Line 23: Line 23:
 
[[file:7080954d-dea9-44c2-b2fb-a9f202a6d76b.png]]
 
[[file:7080954d-dea9-44c2-b2fb-a9f202a6d76b.png]]
  
Imagelists with 32-bit color depth provide native support for alpha channel transparency. By default (which is important ot note), all importing 32-bit bitmaps are treated as transparency-enabled by the component editor.
+
Imagelists with 32-bit color depth provide native support for alpha channel transparency. By default (which is important to note), all importing 32-bit bitmaps are treated as a transparency-enabled by the component editor.
  
In addition to the descripbed aspects, transparent pixels can be affected by `TImageList `component properties, like `BkColor `and `DrawingStyle`.
+
In addition to the descripbed aspects, transparent pixels can be affected by <code>TImageList</code> component properties, like <code>BkColor</code> and <code>DrawingStyle</code>.
  
> So, the colclusion: `TImageList `provides intrinsic transparency, which depends of transparent color, specified during image importing, 32-bit color depth, and, `BkColor` and `DrawingStyle` properties.
+
So, the colclusion: <code>TImageList</code> provides intrinsic transparency, which depends of transparent color, specified during image importing, 32-bit color depth, and, <code>BkColor</code> and <code>DrawingStyle</code> properties.
  
 
=== TVirtualImageList ===
 
=== TVirtualImageList ===
  
As well new virtual image lists can import 32-bit bitmaps, pngs, ect. So, such image lists provide complex (not quite understandable) intrinsic transparency, which we should respected.  
+
As well virtual image lists can import 32-bit bitmaps, pngs, ect. So, such image lists provide complex (not quite understandable) intrinsic transparency, which we should respected.  
  
 
=== TLMDImageList ===
 
=== TLMDImageList ===
  
LMD image list component provides `TLMDCustomImageList.TransparentColor` as "official way" to get information about item transparency. This is used in `LMDIMLTransparentColor` global function. 32-bit images are not supported currently.
+
LMD image list component provides <code>TLMDCustomImageList.TransparentColor</code> as an "official way" to get information about item transparency. This is used in <code>LMDIMLTransparentColor</code> global function. 32-bit images are not supported currently.
  
 
=== Glyph properties ===
 
=== Glyph properties ===
  
Since `TBitmap `type of `Glyph `properties provides no ways to customize transparency during image importing time (as opposed to `TImageList`), all 24-bit bitmaps should be treated as color-key transparent, while all 32-bit bitmaps should be treated as alpha-transparent.
+
Since <code>TBitmap</code> type of <code>Glyph</code> properties provides no ways to customize transparency during image importing time (as opposed to <code>TImageList</code>), all 24-bit bitmaps should be treated as color-key transparent, while all 32-bit bitmaps should be treated as alpha-transparent.
  
 
== Implementation details ==
 
== Implementation details ==
  
LMD- Tools controls almost always draw initial graphics (from image list or a `Glyph `prroperty) onto the temporary bitmap buffer.  
+
LMD-Tools controls almost always draw initial graphics (from image list or a <code>Glyph</code> prroperty) onto the temporary bitmap buffer.  
  
 
=== Image lists ===
 
=== Image lists ===
  
In case of image list graphics source `LMDIMLItemBitmap `function is used.  
+
In case of image list graphics source <code>LMDIMLItemBitmap</code> function is used.  
  
 
For image lists with 32-bit color deptch we adjust destination bitmap pixel format to be also 32-bit, and alpha format to be defined.
 
For image lists with 32-bit color deptch we adjust destination bitmap pixel format to be also 32-bit, and alpha format to be defined.
  
For other (24-bit) image lists its hard if not impossible at all to deduct which transparency rules are really used. Moreover, `TCustomImageList.DoDraw` method is virtual, allowing descendants to do anything. So, in this case we have no better solution than to draw image list item into bitmap, prefilled with some exotic color, and then use this color as a transparent color key. I've declared the following global variable for this:
+
For other (24-bit) image lists it's hard (if not impossible at all) to deduct which transparency rules are really used. Moreover, <code>TCustomImageList.DoDraw</code> method is virtual, allowing descendants to do anything. So, in this case we have no better solution than to draw image list item into bitmap, prefilled with some exotic color, and then use this color as a transparent color key. I've declared the following global variable for this:
  
 
[[file:4be1aa7c-2a6c-4f66-a73b-e0f05b624ffc.png]]
 
[[file:4be1aa7c-2a6c-4f66-a73b-e0f05b624ffc.png]]
Line 57: Line 57:
 
This way all intrinsic image list transparency, described above will be respected as much as possible.
 
This way all intrinsic image list transparency, described above will be respected as much as possible.
  
For controls, which provide `TransparentColor` customization property, the property value is used to fill buffer bitmap instead of global value described above.
+
For controls, which provide <code>TransparentColor</code> customization property, the property value is used to fill buffer bitmap instead of global value described above.
  
 
=== Glyph properties ===
 
=== Glyph properties ===
  
As noted above, 32-bit bitmaps loaded into `Glyph` property are treated as alpha-enabled. However, we cannot set original bitmap `AlphaFormat` to `afDefined`, because this causes internal bitmap data to be premultiplied. And this is wrong, because published property data should be leaved unchanged for potential dfm (re)saving at design-time.
+
As noted above, 32-bit bitmaps loaded into <code>Glyph</code> property are treated as alpha-enabled. However, we cannot set original bitmap <code>AlphaFormat</code> to <code>afDefined</code>, because this causes internal bitmap data to be premultiplied. And this is wrong, because published property data should be leaved unchanged for potential dfm (re)saving at design-time.
  
So, any Glyph property graphics have to be copied into some temporary buffer bitmaps, in which alpha support can be turned on. `TLMDGlyph` class caches and reuses such buffer bitmaps.
+
So, any Glyph property graphics have to be copied into some temporary buffer bitmaps, in which alpha support can be turned on. <code>TLMDGlyph</code> class caches and reuses such buffer bitmaps.
  
Other (24-bit) graphics uses standard `TBitmap.TrnsparentColor` feature to auto-detect transparent color, unless the control provides its own color property.
+
Other (24-bit) graphics uses standard <code>TBitmap.TrnsparentColor</code> feature to auto-detect transparent color, unless the control provides its own color property.
  
=== Internal Api ===
+
=== Internal API ===
  
So, it seems that any kind of transparency can be represented with simple `TBitmap` object, and transfering additional parameters such as `TransparentColor` or `Mask` is not really required. However, for now, and for more explicit code, I've declared special `TLMFGlypTransp `record with some public methods for explicit configuration.
+
So, it seems that any kind of transparency can be represented with simple <code>TBitmap</code> object, and transfering additional parameters such as <code>TransparentColor</code> or <code>Mask</code> is not really required. However, for now, and for more explicit code, I've declared special <code>TLMFGlypTransp</code> record with some public methods for explicit configuration.
  
The record values are used as parameter values in `LMDDrawTextAndGlyph`, `LMDDrawTextAndGlyphExt` and `LMDBmpDrawExt` functions, which was modified to update transparency semantics. These function are now able to draw 32-bit bitmaps, as well, as color-key transparency bitmaps.
+
The record values are used as parameter values in <code>LMDDrawTextAndGlyph</code>, <code>LMDDrawTextAndGlyphExt</code> and <code>LMDBmpDrawExt</code> functions, which was modified to update transparency semantics. These function are now able to draw 32-bit bitmaps, as well, as color-key transparency bitmaps.
  
`LMDIMLItemBitmap` function was also modified to produce 32-bit bitmaps if required, and to support prefilling of 24-bit bitmaps with required color-key.
+
<code>LMDIMLItemBitmap</code> function was also modified to produce 32-bit bitmaps if required, and to support prefilling of 24-bit bitmaps with required color-key.
  
`LMDIMLTransparentColor` function (as has been mentioned above) was modified to report `LMDDefaultImageListTransparentColor` color as a transparent color for non-LMD image lists.
+
<code>LMDIMLTransparentColor</code> function (as has been mentioned above) was modified to report <code>LMDDefaultImageListTransparentColor</code> color as a transparent color for non-LMD image lists.
  
`TLMDGlyph` class was changed also. It does not use image lists to cache bitmaps anymore. Inidividual `TBitmap` objects are used instead. Both: color-key and alpha channel are supported.
+
<code>TLMDGlyph</code> class was changed also. It does not use image lists to cache bitmaps anymore. Inidividual <code>TBitmap</code> objects are used instead. Both: color-key and alpha channel are supported.
  
Also, `TLMDGlyph` class got new `OnGetBitmap` event, which allow to grab the bitmap from other sources (such as image list or standard glyph from resources) leaving `Glyph` bitmap unchanged.
+
Also, <code>TLMDGlyph</code> class got new <code>OnGetBitmap</code> event, which allow to grab the bitmap from other sources (such as image list or standard glyph from resources) leaving <code>Glyph</code> bitmap unchanged.
  
 
=== Controls ===
 
=== Controls ===
  
Controls, which provide several glyph sources, like `Glyph`, `ImageList`/`ImageIndex`, `GlyphKind` properties now implement mutual properties semantic, e.g. setting one of the properties will reset all others to default values. `TLMDGlyph.OnGetBitmap` is used internally.
+
Controls, which provide several glyph sources, like <code>Glyph</code>, <code>ImageList</code>/<code>ImageIndex</code>, <code>GlyphKind</code> properties now implement mutual properties semantic, e.g. setting one of the properties will reset all others to default values. <code>TLMDGlyph.OnGetBitmap</code> is used internally.
  
`TransparentColor` and `GlyphTransparent` control properties are respected using `TLMFGlypTransp` record configuration methods.  In extreme (wrong) case where image list item provides some transparent pixels and, at the same time, `GlyphTransparent` is set to `False`, the user will see `LMDDefaultImageListTransparentColor` backgound.
+
<code>TransparentColor</code> and <code>GlyphTransparent</code> control properties are respected using <code>TLMFGlypTransp</code> record configuration methods.  In extreme (wrong) case where image list item provides some transparent pixels and, at the same time, <code>GlyphTransparent</code> is set to <code>False</code>, the user will see <code>LMDDefaultImageListTransparentColor</code> backgound.
  
For 32-bit graphics `GlyphTransparent` properties are ignored.
+
For 32-bit graphics <code>GlyphTransparent</code> properties are ignored.
  
 
=== Actions ===
 
=== Actions ===
  
Action images are now linked via `ImageList`/`ImageIndex` control's properties, as opposed to old `Glyph` way. Using image lists instead of `Glyph` bitmaps provides auto DPI csaling in case of virtual image lists.
+
Action images are now linked via <code>ImageList</code>/<code>ImageIndex</code> control's properties, as opposed to old <code>Glyph</code> way. Using image lists instead of <code>Glyph</code> bitmaps provides auto DPI csaling in case of virtual image lists.
  
In Delphi action only takes care of `ImageIndex` property, so, control's `ImageList` itself is not affected. I've adjusted this strategy to the following:
+
In Delphi action only takes care of <code>ImageIndex</code> property, so, control's <code>ImageList</code> itself is not affected. I've adjusted this strategy to the following:
  
* if control's `ImageList` is nil, we link it from the corresponding action list.
+
* if control's <code>ImageList</code> is nil, we link it from the corresponding action list.
* Linked `ImageList` can be overidden by the user to another `ImageList`. And, thus, become not linked anymore.
+
* Linked <code>ImageList</code> can be overidden by the user to another <code>ImageList</code>. And, thus, become not linked anymore.
  
 
Linked properties are not stored in dfm.
 
Linked properties are not stored in dfm.
 
=== Design-time editors ===
 
 
`TImageList` standard component editor poorly support 32-bit bitmaps. As well it wrongly import transparent png files. At the same time `TImageList` itself can support all of this stuff very well.
 
 
Another one mising feature - drag&drop image filles directly into the editor. From desktop or file explorer, as well as from special icons tools, like Pichon.
 
 
`Glyph` properties of `TBitmap` type allow to import 32-bit bitmaps correctly. But, custom property editor can also allow to load transparent png files directly into bitmap properties. As well, drag&drop support can be added.
 
 
> So, the idea - develop replacement for standard image list component editor and `TBitmap` property editor.
 
 
=== Font based image list ===
 
 
> We can create new font based image list to be used with Windows 10 Segoe Mdl2 Assets font.
 
 
Not very hard to implement. Will provide:
 
 
* Re-coloring on-the-fly (useful for VCL Styles scenario)
 
* DPI scaling, like virtual image list
 
* Clear type (sub-pixel anti-aliasing)
 
* XE2 support for our own use (in demos), since TVirtualImageList does not exist in XE2, so no DPI scaling of images is possible in XE2.
 
* Much simpler than SVG image list.
 

Latest revision as of 17:18, 7 April 2021

Transparency source

Standard TImageLists

All image list component, including standard TImageList provides some sort of intrinsic transparency. For example:

1ca3303f-b2c6-44a2-b2fd-43d9c8797d7b.png

The icon, shown above, can be imported into image list differently, and will have or have no transparent parts depending of transparent color, specified during importing.

First, let the component editor choose auto transparent color:

6f7fe0a7-5e8c-40f2-905d-3e154b0e853b.png

Second, let override the color:

D5486f3f-21d5-4ac3-8078-760ad9db6be0.png

As a result we'll get two different image list items with different transparent pixels, generated from the same image file. And the second item have no transparent pixels at all, so its magenta backgound should be pained as a part of image to the final destination canvas.

Note also, that transparent colors are not a property of image list items. Colors was used only during importing.

7080954d-dea9-44c2-b2fb-a9f202a6d76b.png

Imagelists with 32-bit color depth provide native support for alpha channel transparency. By default (which is important to note), all importing 32-bit bitmaps are treated as a transparency-enabled by the component editor.

In addition to the descripbed aspects, transparent pixels can be affected by TImageList component properties, like BkColor and DrawingStyle.

So, the colclusion: TImageList provides intrinsic transparency, which depends of transparent color, specified during image importing, 32-bit color depth, and, BkColor and DrawingStyle properties.

TVirtualImageList

As well virtual image lists can import 32-bit bitmaps, pngs, ect. So, such image lists provide complex (not quite understandable) intrinsic transparency, which we should respected.

TLMDImageList

LMD image list component provides TLMDCustomImageList.TransparentColor as an "official way" to get information about item transparency. This is used in LMDIMLTransparentColor global function. 32-bit images are not supported currently.

Glyph properties

Since TBitmap type of Glyph properties provides no ways to customize transparency during image importing time (as opposed to TImageList), all 24-bit bitmaps should be treated as color-key transparent, while all 32-bit bitmaps should be treated as alpha-transparent.

Implementation details

LMD-Tools controls almost always draw initial graphics (from image list or a Glyph prroperty) onto the temporary bitmap buffer.

Image lists

In case of image list graphics source LMDIMLItemBitmap function is used.

For image lists with 32-bit color deptch we adjust destination bitmap pixel format to be also 32-bit, and alpha format to be defined.

For other (24-bit) image lists it's hard (if not impossible at all) to deduct which transparency rules are really used. Moreover, TCustomImageList.DoDraw method is virtual, allowing descendants to do anything. So, in this case we have no better solution than to draw image list item into bitmap, prefilled with some exotic color, and then use this color as a transparent color key. I've declared the following global variable for this:

4be1aa7c-2a6c-4f66-a73b-e0f05b624ffc.png

This way all intrinsic image list transparency, described above will be respected as much as possible.

For controls, which provide TransparentColor customization property, the property value is used to fill buffer bitmap instead of global value described above.

Glyph properties

As noted above, 32-bit bitmaps loaded into Glyph property are treated as alpha-enabled. However, we cannot set original bitmap AlphaFormat to afDefined, because this causes internal bitmap data to be premultiplied. And this is wrong, because published property data should be leaved unchanged for potential dfm (re)saving at design-time.

So, any Glyph property graphics have to be copied into some temporary buffer bitmaps, in which alpha support can be turned on. TLMDGlyph class caches and reuses such buffer bitmaps.

Other (24-bit) graphics uses standard TBitmap.TrnsparentColor feature to auto-detect transparent color, unless the control provides its own color property.

Internal API

So, it seems that any kind of transparency can be represented with simple TBitmap object, and transfering additional parameters such as TransparentColor or Mask is not really required. However, for now, and for more explicit code, I've declared special TLMFGlypTransp record with some public methods for explicit configuration.

The record values are used as parameter values in LMDDrawTextAndGlyph, LMDDrawTextAndGlyphExt and LMDBmpDrawExt functions, which was modified to update transparency semantics. These function are now able to draw 32-bit bitmaps, as well, as color-key transparency bitmaps.

LMDIMLItemBitmap function was also modified to produce 32-bit bitmaps if required, and to support prefilling of 24-bit bitmaps with required color-key.

LMDIMLTransparentColor function (as has been mentioned above) was modified to report LMDDefaultImageListTransparentColor color as a transparent color for non-LMD image lists.

TLMDGlyph class was changed also. It does not use image lists to cache bitmaps anymore. Inidividual TBitmap objects are used instead. Both: color-key and alpha channel are supported.

Also, TLMDGlyph class got new OnGetBitmap event, which allow to grab the bitmap from other sources (such as image list or standard glyph from resources) leaving Glyph bitmap unchanged.

Controls

Controls, which provide several glyph sources, like Glyph, ImageList/ImageIndex, GlyphKind properties now implement mutual properties semantic, e.g. setting one of the properties will reset all others to default values. TLMDGlyph.OnGetBitmap is used internally.

TransparentColor and GlyphTransparent control properties are respected using TLMFGlypTransp record configuration methods. In extreme (wrong) case where image list item provides some transparent pixels and, at the same time, GlyphTransparent is set to False, the user will see LMDDefaultImageListTransparentColor backgound.

For 32-bit graphics GlyphTransparent properties are ignored.

Actions

Action images are now linked via ImageList/ImageIndex control's properties, as opposed to old Glyph way. Using image lists instead of Glyph bitmaps provides auto DPI csaling in case of virtual image lists.

In Delphi action only takes care of ImageIndex property, so, control's ImageList itself is not affected. I've adjusted this strategy to the following:

  • if control's ImageList is nil, we link it from the corresponding action list.
  • Linked ImageList can be overidden by the user to another ImageList. And, thus, become not linked anymore.

Linked properties are not stored in dfm.