summaryrefslogtreecommitdiff
path: root/core/src/fxge/win32/fx_win32_dwrite.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/fxge/win32/fx_win32_dwrite.cpp')
-rw-r--r--core/src/fxge/win32/fx_win32_dwrite.cpp480
1 files changed, 480 insertions, 0 deletions
diff --git a/core/src/fxge/win32/fx_win32_dwrite.cpp b/core/src/fxge/win32/fx_win32_dwrite.cpp
new file mode 100644
index 0000000000..d4c962036e
--- /dev/null
+++ b/core/src/fxge/win32/fx_win32_dwrite.cpp
@@ -0,0 +1,480 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "../../../include/fxge/fx_ge.h"
+#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_
+#include "../../../include/fxge/fx_ge_win32.h"
+#include "dwrite_int.h"
+#include "../Microsoft SDK/include/DWrite.h"
+typedef HRESULT (__stdcall *FuncType_DWriteCreateFactory)(__in DWRITE_FACTORY_TYPE, __in REFIID, __out IUnknown **);
+template <typename InterfaceType>
+inline void SafeRelease(InterfaceType** currentObject)
+{
+ if (*currentObject != NULL) {
+ (*currentObject)->Release();
+ *currentObject = NULL;
+ }
+}
+template <typename InterfaceType>
+inline InterfaceType* SafeAcquire(InterfaceType* newObject)
+{
+ if (newObject != NULL) {
+ newObject->AddRef();
+ }
+ return newObject;
+}
+class CDwFontFileStream : public IDWriteFontFileStream, public CFX_Object
+{
+public:
+ explicit CDwFontFileStream(void const* fontFileReferenceKey, UINT32 fontFileReferenceKeySize);
+ virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
+ virtual ULONG STDMETHODCALLTYPE AddRef();
+ virtual ULONG STDMETHODCALLTYPE Release();
+ virtual HRESULT STDMETHODCALLTYPE ReadFileFragment(void const** fragmentStart, UINT64 fileOffset, UINT64 fragmentSize, OUT void** fragmentContext);
+ virtual void STDMETHODCALLTYPE ReleaseFileFragment(void* fragmentContext);
+ virtual HRESULT STDMETHODCALLTYPE GetFileSize(OUT UINT64* fileSize);
+ virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime(OUT UINT64* lastWriteTime);
+ bool IsInitialized()
+ {
+ return resourcePtr_ != NULL;
+ }
+private:
+ ULONG refCount_;
+ void const* resourcePtr_;
+ DWORD resourceSize_;
+};
+class CDwFontFileLoader : public IDWriteFontFileLoader, public CFX_Object
+{
+public:
+ virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
+ virtual ULONG STDMETHODCALLTYPE AddRef();
+ virtual ULONG STDMETHODCALLTYPE Release();
+ virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey(void const* fontFileReferenceKey, UINT32 fontFileReferenceKeySize, OUT IDWriteFontFileStream** fontFileStream);
+
+ static IDWriteFontFileLoader* GetLoader()
+ {
+ if (instance_ == NULL) {
+ instance_ = FX_NEW CDwFontFileLoader();
+ return instance_;
+ }
+ return instance_;
+ }
+ static bool IsLoaderInitialized()
+ {
+ return instance_ != NULL;
+ }
+private:
+ CDwFontFileLoader();
+ ULONG refCount_;
+ static IDWriteFontFileLoader* instance_;
+};
+class CDwFontContext : public CFX_Object
+{
+public:
+ CDwFontContext(IDWriteFactory* dwriteFactory);
+ ~CDwFontContext();
+ HRESULT Initialize();
+private:
+ CDwFontContext(CDwFontContext const&);
+ void operator=(CDwFontContext const&);
+ HRESULT hr_;
+ IDWriteFactory* dwriteFactory_;
+};
+class CDwGdiTextRenderer : public CFX_Object
+{
+public:
+ CDwGdiTextRenderer(
+ CFX_DIBitmap* pBitmap,
+ IDWriteBitmapRenderTarget* bitmapRenderTarget,
+ IDWriteRenderingParams* renderingParams
+ );
+ CDwGdiTextRenderer::~CDwGdiTextRenderer();
+ HRESULT STDMETHODCALLTYPE DrawGlyphRun(
+ const FX_RECT& text_bbox,
+ __in_opt CFX_ClipRgn* pClipRgn,
+ __in_opt DWRITE_MATRIX const* pMatrix,
+ FLOAT baselineOriginX,
+ FLOAT baselineOriginY,
+ DWRITE_MEASURING_MODE measuringMode,
+ __in DWRITE_GLYPH_RUN const* glyphRun,
+ const COLORREF& textColor
+ );
+private:
+ CFX_DIBitmap* pBitmap_;
+ IDWriteBitmapRenderTarget* pRenderTarget_;
+ IDWriteRenderingParams* pRenderingParams_;
+};
+CDWriteExt::CDWriteExt()
+{
+ m_hModule = NULL;
+ m_pDWriteFactory = NULL;
+ m_pDwFontContext = NULL;
+ m_pDwTextRenderer = NULL;
+}
+void CDWriteExt::Load()
+{
+}
+void CDWriteExt::Unload()
+{
+ if (m_pDwFontContext) {
+ delete (CDwFontContext*)m_pDwFontContext;
+ m_pDwFontContext = NULL;
+ }
+ SafeRelease((IDWriteFactory**)&m_pDWriteFactory);
+}
+CDWriteExt::~CDWriteExt()
+{
+ Unload();
+}
+LPVOID CDWriteExt::DwCreateFontFaceFromStream(FX_LPBYTE pData, FX_DWORD size, int simulation_style)
+{
+ IDWriteFactory* pDwFactory = (IDWriteFactory*)m_pDWriteFactory;
+ IDWriteFontFile* pDwFontFile = NULL;
+ IDWriteFontFace* pDwFontFace = NULL;
+ BOOL isSupportedFontType = FALSE;
+ DWRITE_FONT_FILE_TYPE fontFileType;
+ DWRITE_FONT_FACE_TYPE fontFaceType;
+ UINT32 numberOfFaces;
+ DWRITE_FONT_SIMULATIONS fontStyle = (DWRITE_FONT_SIMULATIONS)(simulation_style & 3);
+ HRESULT hr = S_OK;
+ hr = pDwFactory->CreateCustomFontFileReference(
+ (void const*)pData,
+ (UINT32)size,
+ CDwFontFileLoader::GetLoader(),
+ &pDwFontFile
+ );
+ if (FAILED(hr)) {
+ goto failed;
+ }
+ hr = pDwFontFile->Analyze(
+ &isSupportedFontType,
+ &fontFileType,
+ &fontFaceType,
+ &numberOfFaces
+ );
+ if (FAILED(hr) || !isSupportedFontType || fontFaceType == DWRITE_FONT_FACE_TYPE_UNKNOWN) {
+ goto failed;
+ }
+ hr = pDwFactory->CreateFontFace(
+ fontFaceType,
+ 1,
+ &pDwFontFile,
+ 0,
+ fontStyle,
+ &pDwFontFace
+ );
+ if (FAILED(hr)) {
+ goto failed;
+ }
+ SafeRelease(&pDwFontFile);
+ return pDwFontFace;
+failed:
+ SafeRelease(&pDwFontFile);
+ return NULL;
+}
+FX_BOOL CDWriteExt::DwCreateRenderingTarget(CFX_DIBitmap* pBitmap, void** renderTarget)
+{
+ if (pBitmap->GetFormat() > FXDIB_Argb) {
+ return FALSE;
+ }
+ IDWriteFactory* pDwFactory = (IDWriteFactory*)m_pDWriteFactory;
+ IDWriteGdiInterop* pGdiInterop = NULL;
+ IDWriteBitmapRenderTarget* pBitmapRenderTarget = NULL;
+ IDWriteRenderingParams* pRenderingParams = NULL;
+ HRESULT hr = S_OK;
+ hr = pDwFactory->GetGdiInterop(&pGdiInterop);
+ if (FAILED(hr)) {
+ goto failed;
+ }
+ hr = pGdiInterop->CreateBitmapRenderTarget(NULL, pBitmap->GetWidth(), pBitmap->GetHeight(),
+ &pBitmapRenderTarget);
+ if (FAILED(hr)) {
+ goto failed;
+ }
+ hr = pDwFactory->CreateCustomRenderingParams(
+ 1.0f,
+ 0.0f,
+ 1.0f,
+ DWRITE_PIXEL_GEOMETRY_RGB,
+ DWRITE_RENDERING_MODE_DEFAULT,
+ &pRenderingParams
+ );
+ if (FAILED(hr)) {
+ goto failed;
+ }
+ hr = pBitmapRenderTarget->SetPixelsPerDip(1.0f);
+ if (FAILED(hr)) {
+ goto failed;
+ }
+ *(CDwGdiTextRenderer**)renderTarget = FX_NEW CDwGdiTextRenderer(pBitmap, pBitmapRenderTarget, pRenderingParams);
+ if (*(CDwGdiTextRenderer**)renderTarget == NULL) {
+ goto failed;
+ }
+ SafeRelease(&pGdiInterop);
+ SafeRelease(&pBitmapRenderTarget);
+ SafeRelease(&pRenderingParams);
+ return TRUE;
+failed:
+ SafeRelease(&pGdiInterop);
+ SafeRelease(&pBitmapRenderTarget);
+ SafeRelease(&pRenderingParams);
+ return FALSE;
+}
+FX_BOOL CDWriteExt::DwRendingString(void* renderTarget, CFX_ClipRgn* pClipRgn, FX_RECT& stringRect, CFX_AffineMatrix* pMatrix,
+ void *font, FX_FLOAT font_size, FX_ARGB text_color,
+ int glyph_count, unsigned short* glyph_indices,
+ FX_FLOAT baselineOriginX, FX_FLOAT baselineOriginY,
+ void* glyph_offsets,
+ FX_FLOAT* glyph_advances)
+{
+ if (renderTarget == NULL) {
+ return TRUE;
+ }
+ CDwGdiTextRenderer* pTextRenderer = (CDwGdiTextRenderer*)renderTarget;
+ DWRITE_MATRIX transform;
+ DWRITE_GLYPH_RUN glyphRun;
+ HRESULT hr = S_OK;
+ if (pMatrix) {
+ transform.m11 = pMatrix->a;
+ transform.m12 = pMatrix->b;
+ transform.m21 = pMatrix->c;
+ transform.m22 = pMatrix->d;
+ transform.dx = pMatrix->e;
+ transform.dy = pMatrix->f;
+ }
+ glyphRun.fontFace = (IDWriteFontFace*)font;
+ glyphRun.fontEmSize = font_size;
+ glyphRun.glyphCount = glyph_count;
+ glyphRun.glyphIndices = glyph_indices;
+ glyphRun.glyphAdvances = glyph_advances;
+ glyphRun.glyphOffsets = (DWRITE_GLYPH_OFFSET*)glyph_offsets;
+ glyphRun.isSideways = FALSE;
+ glyphRun.bidiLevel = 0;
+ hr = pTextRenderer->DrawGlyphRun(
+ stringRect,
+ pClipRgn,
+ pMatrix ? &transform : NULL,
+ baselineOriginX, baselineOriginY,
+ DWRITE_MEASURING_MODE_NATURAL,
+ &glyphRun,
+ RGB(FXARGB_R(text_color), FXARGB_G(text_color), FXARGB_B(text_color))
+ );
+ return SUCCEEDED(hr) ? TRUE : FALSE;
+}
+void CDWriteExt::DwDeleteRenderingTarget(void* renderTarget)
+{
+ if (renderTarget) {
+ delete (CDwGdiTextRenderer*)renderTarget;
+ }
+}
+void CDWriteExt::DwDeleteFont(void* pFont)
+{
+ if (pFont) {
+ SafeRelease((IDWriteFontFace**)&pFont);
+ }
+}
+CDwFontFileStream::CDwFontFileStream(void const* fontFileReferenceKey, UINT32 fontFileReferenceKeySize)
+{
+ refCount_ = 0;
+ resourcePtr_ = fontFileReferenceKey;
+ resourceSize_ = fontFileReferenceKeySize;
+}
+HRESULT STDMETHODCALLTYPE CDwFontFileStream::QueryInterface(REFIID iid, void** ppvObject)
+{
+ if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileStream)) {
+ *ppvObject = this;
+ AddRef();
+ return S_OK;
+ } else {
+ *ppvObject = NULL;
+ return E_NOINTERFACE;
+ }
+}
+ULONG STDMETHODCALLTYPE CDwFontFileStream::AddRef()
+{
+ return InterlockedIncrement((long*)(&refCount_));
+}
+ULONG STDMETHODCALLTYPE CDwFontFileStream::Release()
+{
+ ULONG newCount = InterlockedDecrement((long*)(&refCount_));
+ if (newCount == 0) {
+ delete this;
+ }
+ return newCount;
+}
+HRESULT STDMETHODCALLTYPE CDwFontFileStream::ReadFileFragment(
+ void const** fragmentStart,
+ UINT64 fileOffset,
+ UINT64 fragmentSize,
+ OUT void** fragmentContext
+)
+{
+ if (fileOffset <= resourceSize_ &&
+ fragmentSize <= resourceSize_ - fileOffset) {
+ *fragmentStart = static_cast<FX_BYTE const*>(resourcePtr_) + static_cast<size_t>(fileOffset);
+ *fragmentContext = NULL;
+ return S_OK;
+ } else {
+ *fragmentStart = NULL;
+ *fragmentContext = NULL;
+ return E_FAIL;
+ }
+}
+void STDMETHODCALLTYPE CDwFontFileStream::ReleaseFileFragment(void* fragmentContext)
+{
+}
+HRESULT STDMETHODCALLTYPE CDwFontFileStream::GetFileSize(OUT UINT64* fileSize)
+{
+ *fileSize = resourceSize_;
+ return S_OK;
+}
+HRESULT STDMETHODCALLTYPE CDwFontFileStream::GetLastWriteTime(OUT UINT64* lastWriteTime)
+{
+ *lastWriteTime = 0;
+ return E_NOTIMPL;
+}
+IDWriteFontFileLoader* CDwFontFileLoader::instance_ = NULL;
+CDwFontFileLoader::CDwFontFileLoader() :
+ refCount_(0)
+{
+}
+HRESULT STDMETHODCALLTYPE CDwFontFileLoader::QueryInterface(REFIID iid, void** ppvObject)
+{
+ if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) {
+ *ppvObject = this;
+ AddRef();
+ return S_OK;
+ } else {
+ *ppvObject = NULL;
+ return E_NOINTERFACE;
+ }
+}
+ULONG STDMETHODCALLTYPE CDwFontFileLoader::AddRef()
+{
+ return InterlockedIncrement((long*)(&refCount_));
+}
+ULONG STDMETHODCALLTYPE CDwFontFileLoader::Release()
+{
+ ULONG newCount = InterlockedDecrement((long*)(&refCount_));
+ if (newCount == 0) {
+ instance_ = NULL;
+ delete this;
+ }
+ return newCount;
+}
+HRESULT STDMETHODCALLTYPE CDwFontFileLoader::CreateStreamFromKey(
+ void const* fontFileReferenceKey,
+ UINT32 fontFileReferenceKeySize,
+ OUT IDWriteFontFileStream** fontFileStream
+)
+{
+ *fontFileStream = NULL;
+ CDwFontFileStream* stream = FX_NEW CDwFontFileStream(fontFileReferenceKey, fontFileReferenceKeySize);
+ if (stream == NULL) {
+ return E_OUTOFMEMORY;
+ }
+ if (!stream->IsInitialized()) {
+ delete stream;
+ return E_FAIL;
+ }
+ *fontFileStream = SafeAcquire(stream);
+ return S_OK;
+}
+CDwFontContext::CDwFontContext(IDWriteFactory* dwriteFactory) :
+ hr_(S_FALSE),
+ dwriteFactory_(SafeAcquire(dwriteFactory))
+{
+}
+CDwFontContext::~CDwFontContext()
+{
+ if(dwriteFactory_ && hr_ == S_OK) {
+ dwriteFactory_->UnregisterFontFileLoader(CDwFontFileLoader::GetLoader());
+ }
+ SafeRelease(&dwriteFactory_);
+}
+HRESULT CDwFontContext::Initialize()
+{
+ if (hr_ == S_FALSE) {
+ return hr_ = dwriteFactory_->RegisterFontFileLoader(CDwFontFileLoader::GetLoader());
+ }
+ return hr_;
+}
+CDwGdiTextRenderer::CDwGdiTextRenderer(CFX_DIBitmap* pBitmap, IDWriteBitmapRenderTarget* bitmapRenderTarget, IDWriteRenderingParams* renderingParams):
+ pBitmap_(pBitmap),
+ pRenderTarget_(SafeAcquire(bitmapRenderTarget)),
+ pRenderingParams_(SafeAcquire(renderingParams))
+{
+}
+CDwGdiTextRenderer::~CDwGdiTextRenderer()
+{
+ SafeRelease(&pRenderTarget_);
+ SafeRelease(&pRenderingParams_);
+}
+STDMETHODIMP CDwGdiTextRenderer::DrawGlyphRun(
+ const FX_RECT& text_bbox,
+ __in_opt CFX_ClipRgn* pClipRgn,
+ __in_opt DWRITE_MATRIX const* pMatrix,
+ FLOAT baselineOriginX,
+ FLOAT baselineOriginY,
+ DWRITE_MEASURING_MODE measuringMode,
+ __in DWRITE_GLYPH_RUN const* glyphRun,
+ const COLORREF& textColor
+)
+{
+ HRESULT hr = S_OK;
+ if (pMatrix) {
+ hr = pRenderTarget_->SetCurrentTransform(pMatrix);
+ if (FAILED(hr)) {
+ return hr;
+ }
+ }
+ HDC hDC = pRenderTarget_->GetMemoryDC();
+ HBITMAP hBitmap = (HBITMAP)::GetCurrentObject(hDC, OBJ_BITMAP);
+ BITMAP bitmap;
+ GetObject(hBitmap, sizeof bitmap, &bitmap);
+ CFX_DIBitmap dib;
+ dib.Create(
+ bitmap.bmWidth,
+ bitmap.bmHeight,
+ bitmap.bmBitsPixel == 24 ? FXDIB_Rgb : FXDIB_Rgb32,
+ (FX_LPBYTE)bitmap.bmBits
+ );
+ dib.CompositeBitmap(
+ text_bbox.left,
+ text_bbox.top,
+ text_bbox.Width(),
+ text_bbox.Height(),
+ pBitmap_,
+ text_bbox.left,
+ text_bbox.top,
+ FXDIB_BLEND_NORMAL,
+ NULL
+ );
+ hr = pRenderTarget_->DrawGlyphRun(
+ baselineOriginX,
+ baselineOriginY,
+ measuringMode,
+ glyphRun,
+ pRenderingParams_,
+ textColor
+ );
+ if (FAILED(hr)) {
+ return hr;
+ }
+ pBitmap_->CompositeBitmap(
+ text_bbox.left,
+ text_bbox.top,
+ text_bbox.Width(),
+ text_bbox.Height(),
+ &dib,
+ text_bbox.left,
+ text_bbox.top,
+ FXDIB_BLEND_NORMAL,
+ pClipRgn
+ );
+ return hr;
+}
+#endif