This seems like overkill to me?
I don't see the need for per-object refcounting. Every drawing operation that uses an object is just going to end with a series of releases, and after it returns all refcounts should be 0.
+ /* TODO: object id should be released on object dispose */ I don't think this approach is possible. It would require every object to be aware of which metafiles are using it, and every operation that modifies the object would have to release them. Bitmap objects can refer to an application buffer that could be modified without any call into gdiplus. (Or, Bitmaps could be modified by an ImageAttributes, in which case we can't reuse them except with an identical ImageAttributes.)
If we wanted to reuse Bitmaps, we'd have to compare the data. For other large types like Paths, maybe keeping an id to detect whether it changed would make sense. For types of bounded size, it probably would be easier to store a complete copy.