Menu

#493 Copy semantics for GDI objects are inconsistent

unspecified
pending
nobody
1
2026-07-30
2021-04-12
No

The TGdiObject base class is designed as a reference-counted encapsulation around a GDI handle (e.g. HPEN, HBRUSH, HFONT, HPALETTE and HBITMAP). In effect, it works like a smart pointer. Many objects can be made, all encapsulating the same handle, i.e. the same underlying object. Copying a TGdiObject instance does not copy the underlying object pointed to by the handle. It merely copies the handle and keeps track of reference counts.

However, the derived classes (TPen, TBrush, TFont, TPalette and TBitmap) are not consistent in their copy semantics. In particular, TPalette and TBitmap implement deep copy in their copy constructors, as if these classes encapsulated the object, not just the handle. In short, they do not behave like smart pointers, as intended by the TGdiObject base class design.

The deep copying should be moved to a named member function (e.g. DeepCopy), and the copy constructors should behave consistently like smart pointers. Also, move constructors should be implemented, to eliminate superfluous and inefficient reference count updates.

Related

Discussion: Selecting and restoring objects in TDC
Feature Requests: #178
News: 2026/08/owlet---gdi-overhaul-and-new-shared-pointer-semantics

Discussion

  • Vidar Hasfjord

    Vidar Hasfjord - 2021-04-12
    • status: open --> pending
     
  • Vidar Hasfjord

    Vidar Hasfjord - 2021-04-12

    This issue was fixed as proposed in Owlet in [r5430].

    This revision also adds move constructors.

     

    Related

    Commit: [r5430]

  • Vidar Hasfjord

    Vidar Hasfjord - 2026-03-27
    • assigned_to: Vidar Hasfjord --> nobody
     
  • Ognyan Chernokozhev

    I think it would be best to have this change in the trunk for the future OWLNext 8 release.

     
    👍
    1
  • Vidar Hasfjord

    Vidar Hasfjord - 2026-07-30

    @jogybl wrote:

    I think it would be best to have this change in the trunk for the future OWLNext 8 release.

    Thanks for the feedback. I created this ticket a long time ago, when version 7 was still the trunk. Now, having retired, I no longer intend to take on the work to merge my changes into the trunk, but feel free to go ahead if you feel brave. :-)

    The reason I updated this ticket now, is that I've returned to my overhaul of the GDI classes in Owlet, attempting to eliminate TGdiBase (with TGdiObject already eliminated), replaced by std::shared_ptr, thereby giving all the derived classes proper shared pointer semantics. I will post more on this when I complete the work.

     

    Last edit: Vidar Hasfjord 2026-07-30

Log in to post a comment.