Currently, TGdiObject is the base class for the GDI handle encapsulation classes TBrush, TPen, TFont, TPalette and TBitmap, which encapsulate HBRUSH, HPEN, HFONT, HPALETTE and HBITMAP handles, respectively, which can be selected into a device context to set the GDI state for drawing. TGdiObject provides functionality for reference counted handle sharing, in which TDC also participates for handles selected into a device context using TDC::SelectObject.
However, the reference counting implementation is poorly understood and hard to maintain. Copy and move semantics are confusing, and often implemented in contradictory manner [bugs:#493]. The reference counted cache in TBrush further exacerbates the maintenance problem. For example, see [bugs:#495].
TGdiObject can be replaced by a simpler and more consistent implementation based on std::shared_ptr, thereby removing all the reference counting code altogether. Then we can instead simply rely on the tried and tested implementation of std::shared_ptr.
I also propose that TDC::SelectObject stops taking references to the selected objects (a.k.a. "orhpan control"). Client code should instead be properly written not to rely on orphans (the keeping alive of dangling handles), and instead properly clean up GDI state, by ideally always restoring the old state after a drawing operation, or alternatively, be written not to rely on state from a previous scope. In short, set the intended GDI state before a drawing operation, unless you can be sure the current state is already the desired state. With new extensions this is now feasible. See [feature-requests:#175] and [feature-requests:#176].
I have trialled these changes in Owlet and my main OWLNext application. The latter uses GDI extensively and works perfectly well without orphan control. See "Selecting and restoring GDI objects in TDC" for a full discussion.
Bugs: #493
Bugs: #495
Discussion: Selecting and restoring objects in TDC
Discussion: Selecting and restoring objects in TDC
Feature Requests: #175
Feature Requests: #176
Feature Requests: #204
Feature Requests: #210
Wiki: Selecting_and_restoring_objects_in_TDC
Anonymous
Much of the proposed overhaul was implemented in [r5484].
Further overhaul may be performed, in particular by the replacement of TGdiBase also by std::shared_ptr, with the overhaul of the API, the copy and move semantics, and the implementation and documentation of the related classes, such as TDC, TRegion, TDib, etc.
Edit: A separate ticket has been created for further work on shared-pointer semantics. See "Shared-pointer semantics for handle-encapsulating classes" [feature-requests:#210].
Related
Commit: [r5484]
Feature Requests: #210
Last edit: Vidar Hasfjord 2022-06-16