/**************************************************************************\ * * Copyright (c) 1999 Microsoft Corporation * * Module Name: * * Object.hpp * * Abstract: * * GpObject interface class * * Created: * * 4/22/1999 DCurtis * \**************************************************************************/ #ifndef _OBJECT_HPP #define _OBJECT_HPP // The version must be changed when any EMF+ record is changed, including // when an object record is changed. // Changes that invalidate previous files require a major version number change. // Other changes just require a minor version number change. #define EMFPLUS_VERSION 0xdbc01001 #define EMFPLUS_MAJORVERSION_BITS 0xFFFFF000 #define EMFPLUS_MINORVERSION_BITS 0x00000FFF // The GetData methods for all objects must all return a data buffer that // has a version number as the first INT32 field. class ObjectData { public: INT32 Version; ObjectData() { Version = EMFPLUS_VERSION; } // We should be able to understand the data format as long as the // major version numbers match. The code must be able to handle // minor version number changes. BOOL MajorVersionMatches() const { return MajorVersionMatches(Version); } static BOOL MajorVersionMatches(INT version) { return ((version & EMFPLUS_MAJORVERSION_BITS) == (EMFPLUS_VERSION & EMFPLUS_MAJORVERSION_BITS)); } }; class ObjectTypeData : public ObjectData { public: INT32 Type; }; VOID InitVersionInfo(); enum EmfPlusRecordType; enum ColorAdjustType; class GpRecolor; class GpObject { public: GpObject() { Uid = 0; Tag = ObjectTagInvalid; // Invalid state } virtual ~GpObject() { // Force the object to be invalid so we can't reuse this // deleted object accidentally. Tag = ObjectTagInvalid; // Invalid state } virtual BOOL IsValid() const = 0; BOOL IsValid(ObjectTag objectTag) const { #ifdef _X86_ // We have to guarantee that the Tag field doesn't move for // versioning to work between releases of GDI+. ASSERT(offsetof(GpObject, Tag) == 4); #endif ASSERT((objectTag & 0xff) == '1'); #if DBG if (Tag == ObjectTagInvalid) { WARNING1("Invalid Object"); } else if ((Tag & 0xff) != '1') { WARNING1("Object created by different version of GDI+") } else { ASSERT(objectTag == Tag); } #endif return (objectTag == Tag); } VOID SetValid(ObjectTag objectTag) { ASSERT((objectTag == ObjectTagInvalid) || ((objectTag & 0xff) == '1')) Tag = objectTag; } virtual ObjectType GetObjectType() const = 0; virtual UINT GetDataSize() const = 0; virtual GpStatus GetData(BYTE * dataBuffer, UINT & size) const; virtual GpStatus GetData(IStream * stream) const = 0; virtual GpStatus SetData(const BYTE * dataBuffer, UINT size) = 0; virtual GpStatus ColorAdjust( GpRecolor * recolor, ColorAdjustType type ) { return Ok; } virtual VOID Dispose() { delete this; } UINT GetExternalDataSize() const; GpStatus GetExternalData(BYTE * dataBuffer, UINT & size); GpStatus SetExternalData(const BYTE * data, UINT size); UINT GetUid() const { if(Uid == 0) { Uid = GpObject::GenerateUniqueness(); } return (UINT)Uid; } VOID UpdateUid() { Uid = 0; } // SetUid is useful in cloning operations. VOID SetUid(UINT newUid) { Uid = (LONG_PTR)newUid; } // Object factory for creating an object from metafile memory static GpObject * Factory( ObjectType type, const ObjectData * objectData, UINT size ); static LONG_PTR GenerateUniqueness( ) { LONG_PTR Uid; // !!! Until we get a way to make sure GDI+ has been initialized when // !!! using it as a static lib, we need this check because if there // !!! is a global object, this could get called before // !!! InitializeGdiplus() is called (for static lib case). if (!Globals::VersionInfoInitialized) { InitVersionInfo(); } // Use InterlockedCompareExchangeFunction instead of // InterlockedIncrement, because InterlockedIncrement doesn't work // the way we need it to on Win9x. do { Uid = Uniqueness; } while (CompareExchangeLong_Ptr(&Uniqueness, (Uid + 1), Uid) != Uid); return (Uid + 1); } private: // These members are declared as LONG_PTR because they have to be aligned // to, and sized according to the minimum atomically exchangable object. // On x86 this is 32bits and on IA64 this is 64bits. static LONG_PTR Uniqueness; // We now use an ObjectTag to determine if the object is valid // instead of using a BOOL. This is much more robust and helps // with debugging. It also enables us to version our objects // more easily with a version number in the ObjectTag. ObjectTag Tag; // Keep this as the 1st value in the object! mutable LONG_PTR Uid; }; #endif // !_OBJECT_HPP