summaryrefslogtreecommitdiff
path: root/core/fxge/win32/fx_win32_dwrite.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/fxge/win32/fx_win32_dwrite.cpp')
-rw-r--r--core/fxge/win32/fx_win32_dwrite.cpp410
1 files changed, 410 insertions, 0 deletions
diff --git a/core/fxge/win32/fx_win32_dwrite.cpp b/core/fxge/win32/fx_win32_dwrite.cpp
new file mode 100644
index 0000000000..972295c5cc
--- /dev/null
+++ b/core/fxge/win32/fx_win32_dwrite.cpp
@@ -0,0 +1,410 @@
+// 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 "core/include/fxge/fx_ge.h"
+
+#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_
+#include <dwrite.h>
+
+#include "core/fxge/win32/dwrite_int.h"
+#include "core/include/fxge/fx_ge_win32.h"
+
+typedef HRESULT(__stdcall* FuncType_DWriteCreateFactory)(
+ __in DWRITE_FACTORY_TYPE,
+ __in REFIID,
+ __out IUnknown**);
+template <typename InterfaceType>
+inline void SafeRelease(InterfaceType** currentObject) {
+ if (*currentObject) {
+ (*currentObject)->Release();
+ *currentObject = NULL;
+ }
+}
+template <typename InterfaceType>
+inline InterfaceType* SafeAcquire(InterfaceType* newObject) {
+ if (newObject) {
+ newObject->AddRef();
+ }
+ return newObject;
+}
+class CDwFontFileStream final : public IDWriteFontFileStream {
+ 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 final : public IDWriteFontFileLoader {
+ 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_) {
+ instance_ = new CDwFontFileLoader();
+ }
+ return instance_;
+ }
+ static bool IsLoaderInitialized() { return instance_ != NULL; }
+
+ private:
+ CDwFontFileLoader();
+ ULONG refCount_;
+ static IDWriteFontFileLoader* instance_;
+};
+class CDwFontContext {
+ public:
+ CDwFontContext(IDWriteFactory* dwriteFactory);
+ ~CDwFontContext();
+ HRESULT Initialize();
+
+ private:
+ CDwFontContext(CDwFontContext const&);
+ void operator=(CDwFontContext const&);
+ HRESULT hr_;
+ IDWriteFactory* dwriteFactory_;
+};
+class CDwGdiTextRenderer {
+ public:
+ CDwGdiTextRenderer(CFX_DIBitmap* pBitmap,
+ IDWriteBitmapRenderTarget* bitmapRenderTarget,
+ IDWriteRenderingParams* renderingParams);
+ ~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(uint8_t* 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 =
+ new CDwGdiTextRenderer(pBitmap, pBitmapRenderTarget, pRenderingParams);
+ 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_Matrix* 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) {
+ 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);
+}
+void CDWriteExt::DwDeleteRenderingTarget(void* 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;
+ }
+ *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<uint8_t const*>(resourcePtr_) +
+ static_cast<size_t>(fileOffset);
+ *fragmentContext = NULL;
+ return S_OK;
+ }
+ *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;
+ }
+ *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 =
+ new CDwFontFileStream(fontFileReferenceKey, fontFileReferenceKeySize);
+ 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,
+ (uint8_t*)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