WindowsXP-SP1/windows/advcore/gdiplus/engine/entry/object.hpp
2020-09-30 16:53:49 +02:00

199 lines
5.5 KiB
C++

/**************************************************************************\
*
* 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