265 lines
6.4 KiB
C++
265 lines
6.4 KiB
C++
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
|
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
|
// PARTICULAR PURPOSE.
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved
|
|
//
|
|
// Contents: Shared definitions.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#pragma once
|
|
|
|
// The following macros define the minimum required platform. The minimum required platform
|
|
// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run
|
|
// your application. The macros work by enabling all features available on platform versions up to and
|
|
// including the version specified.
|
|
|
|
// Modify the following defines if you have to target a platform prior to the ones specified below.
|
|
// Refer to MSDN for the latest info on corresponding values for different platforms.
|
|
|
|
#ifndef WINVER // Minimum platform is Windows 7
|
|
#define WINVER 0x0601
|
|
#endif
|
|
|
|
#ifndef _WIN32_WINNT // Minimum platform is Windows 7
|
|
#define _WIN32_WINNT 0x0601
|
|
#endif
|
|
|
|
#ifndef _WIN32_WINDOWS // Minimum platform is Windows 7
|
|
#define _WIN32_WINDOWS 0x0601
|
|
#endif
|
|
|
|
#ifndef WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#endif
|
|
|
|
#ifndef NOMINMAX // Use the standard's templated min/max
|
|
#define NOMINMAX
|
|
#endif
|
|
|
|
#ifndef _USE_MATH_DEFINES // want PI defined
|
|
#define _USE_MATH_DEFINES
|
|
#endif
|
|
|
|
////////////////////////////////////////
|
|
// Common headers:
|
|
|
|
// C headers:
|
|
#include <stdlib.h>
|
|
#include <malloc.h>
|
|
#include <memory.h>
|
|
#include <math.h>
|
|
|
|
// C++ headers:
|
|
#include <algorithm>
|
|
#include <numeric>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <utility>
|
|
#include <limits>
|
|
|
|
// Windows headers:
|
|
|
|
#include <windows.h>
|
|
#include <windowsx.h>
|
|
#include <unknwn.h>
|
|
|
|
#include <dwrite.h>
|
|
#include <intsafe.h>
|
|
#include <strsafe.h>
|
|
|
|
|
|
////////////////////////////////////////
|
|
// Common macro definitions:
|
|
|
|
#ifndef HINST_THISCOMPONENT
|
|
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
|
|
#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
|
|
#endif
|
|
|
|
// Use the double macro technique to stringize the actual value of s
|
|
#define STRINGIZE_(s) STRINGIZE2_(s)
|
|
#define STRINGIZE2_(s) #s
|
|
|
|
#define FAILURE_LOCATION L"\r\nFunction: " TEXT(__FUNCTION__) L"\r\nLine: " TEXT(STRINGIZE_(__LINE__))
|
|
|
|
#if (_MSC_VER >= 1200) // want to use std::min and std::max
|
|
#undef min
|
|
#undef max
|
|
#define min(x,y) _cpp_min(x,y)
|
|
#define max(x,y) _cpp_max(x,y)
|
|
#endif
|
|
|
|
// Ignore unreferenced parameters, since they are very common
|
|
// when implementing callbacks.
|
|
#pragma warning(disable : 4100)
|
|
|
|
|
|
////////////////////////////////////////
|
|
// Application specific headers/functions:
|
|
|
|
#define APPLICATION_TITLE "CustomLayout - DirectWrite script layer SDK sample"
|
|
|
|
|
|
////////////////////////////////////////
|
|
// COM inheritance helpers.
|
|
|
|
|
|
// Releases a COM object and nullifies pointer.
|
|
template <typename InterfaceType>
|
|
inline void SafeRelease(InterfaceType** currentObject)
|
|
{
|
|
if (*currentObject != NULL)
|
|
{
|
|
(*currentObject)->Release();
|
|
*currentObject = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
// Acquires an additional reference, if non-null.
|
|
template <typename InterfaceType>
|
|
inline InterfaceType* SafeAcquire(InterfaceType* newObject)
|
|
{
|
|
if (newObject != NULL)
|
|
newObject->AddRef();
|
|
|
|
return newObject;
|
|
}
|
|
|
|
|
|
// Sets a new COM object, releasing the old one.
|
|
template <typename InterfaceType>
|
|
inline void SafeSet(InterfaceType** currentObject, InterfaceType* newObject)
|
|
{
|
|
SafeAcquire(newObject);
|
|
SafeRelease(currentObject);
|
|
*currentObject = newObject;
|
|
}
|
|
|
|
|
|
// Maps exceptions to equivalent HRESULTs,
|
|
inline HRESULT ExceptionToHResult() throw()
|
|
{
|
|
try
|
|
{
|
|
throw; // Rethrow previous exception.
|
|
}
|
|
catch(std::bad_alloc&)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
catch (...)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
}
|
|
|
|
|
|
// Generic COM base implementation for classes, since DirectWrite uses
|
|
// callbacks for several different kinds of objects, particularly the
|
|
// script analysis source/sink.
|
|
//
|
|
// Example:
|
|
//
|
|
// class TextAnalysis : public ComBase<QiList<IDWriteTextAnalysisSink> >
|
|
//
|
|
template <typename InterfaceChain>
|
|
class ComBase : public InterfaceChain
|
|
{
|
|
public:
|
|
explicit ComBase() throw()
|
|
: refValue_(0)
|
|
{ }
|
|
|
|
// IUnknown interface
|
|
IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject)
|
|
{
|
|
*ppObject = NULL;
|
|
InterfaceChain::QueryInterfaceInternal(iid, ppObject);
|
|
if (*ppObject == NULL)
|
|
return E_NOINTERFACE;
|
|
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
IFACEMETHOD_(ULONG, AddRef)()
|
|
{
|
|
return InterlockedIncrement(&refValue_);
|
|
}
|
|
|
|
IFACEMETHOD_(ULONG, Release)()
|
|
{
|
|
ULONG newCount = InterlockedDecrement(&refValue_);
|
|
if (newCount == 0)
|
|
delete this;
|
|
|
|
return newCount;
|
|
}
|
|
|
|
virtual ~ComBase()
|
|
{ }
|
|
|
|
protected:
|
|
ULONG refValue_;
|
|
|
|
private:
|
|
// No copy construction allowed.
|
|
ComBase(const ComBase& b);
|
|
ComBase& operator=(ComBase const&);
|
|
};
|
|
|
|
|
|
struct QiListNil
|
|
{
|
|
};
|
|
|
|
|
|
// When the QueryInterface list refers to itself as class,
|
|
// which hasn't fully been defined yet.
|
|
template <typename InterfaceName, typename InterfaceChain>
|
|
class QiListSelf : public InterfaceChain
|
|
{
|
|
public:
|
|
inline void QueryInterfaceInternal(IID const& iid, OUT void** ppObject) throw()
|
|
{
|
|
if (iid != __uuidof(InterfaceName))
|
|
return InterfaceChain::QueryInterfaceInternal(iid, ppObject);
|
|
|
|
*ppObject = static_cast<InterfaceName*>(this);
|
|
}
|
|
};
|
|
|
|
|
|
// When this interface is implemented and more follow.
|
|
template <typename InterfaceName, typename InterfaceChain = QiListNil>
|
|
class QiList : public InterfaceName, public InterfaceChain
|
|
{
|
|
public:
|
|
inline void QueryInterfaceInternal(IID const& iid, OUT void** ppObject) throw()
|
|
{
|
|
if (iid != __uuidof(InterfaceName))
|
|
return InterfaceChain::QueryInterfaceInternal(iid, ppObject);
|
|
|
|
*ppObject = static_cast<InterfaceName*>(this);
|
|
}
|
|
};
|
|
|
|
|
|
// When the this is the last implemented interface in the list.
|
|
template <typename InterfaceName>
|
|
class QiList<InterfaceName, QiListNil> : public InterfaceName
|
|
{
|
|
public:
|
|
inline void QueryInterfaceInternal(IID const& iid, OUT void** ppObject) throw()
|
|
{
|
|
if (iid != __uuidof(InterfaceName))
|
|
return;
|
|
|
|
*ppObject = static_cast<InterfaceName*>(this);
|
|
}
|
|
};
|